2 Copyright (C) 2009 Paul Davis
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)
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
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.
22 #include "pbd/enumwriter.h"
23 #include "pbd/convert.h"
25 #include "ardour/amp.h"
26 #include "ardour/audioengine.h"
27 #include "ardour/buffer_set.h"
28 #include "ardour/debug.h"
29 #include "ardour/delivery.h"
30 #include "ardour/io.h"
31 #include "ardour/mute_master.h"
32 #include "ardour/pannable.h"
33 #include "ardour/panner_shell.h"
34 #include "ardour/port.h"
35 #include "ardour/session.h"
39 namespace ARDOUR { class Panner; }
43 using namespace ARDOUR;
45 PBD::Signal0<void> Delivery::PannersLegal;
46 bool Delivery::panners_legal = false;
48 /* deliver to an existing IO object */
50 Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<Pannable> pannable,
51 boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
52 : IOProcessor(s, boost::shared_ptr<IO>(), (role_requires_output_ports (r) ? io : boost::shared_ptr<IO>()), name)
54 , _output_buffers (new BufferSet())
55 , _current_gain (GAIN_COEFF_UNITY)
56 , _no_outs_cuz_we_no_monitor (false)
58 , _no_panner_reset (false)
62 if (r & (Delivery::Send|Delivery::Aux)) is_send = true;
63 _panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable, is_send));
66 _display_to_user = false;
69 _output->changed.connect_same_thread (*this, boost::bind (&Delivery::output_changed, this, _1, _2));
73 /* deliver to a new IO object */
75 Delivery::Delivery (Session& s, boost::shared_ptr<Pannable> pannable, boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
76 : IOProcessor(s, false, (role_requires_output_ports (r) ? true : false), name, "", DataType::AUDIO, (r == Send))
78 , _output_buffers (new BufferSet())
79 , _current_gain (GAIN_COEFF_UNITY)
80 , _no_outs_cuz_we_no_monitor (false)
82 , _no_panner_reset (false)
86 if (r & (Delivery::Send|Delivery::Aux)) is_send = true;
87 _panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable, is_send));
90 _display_to_user = false;
93 _output->changed.connect_same_thread (*this, boost::bind (&Delivery::output_changed, this, _1, _2));
100 DEBUG_TRACE (DEBUG::Destruction, string_compose ("delivery %1 destructor\n", _name));
102 /* this object should vanish from any signal callback lists
103 that it is on before we get any further. The full qualification
104 of the method name is not necessary, but is here to make it
105 clear that this call is about signals, not data flow connections.
108 ScopedConnectionList::drop_connections ();
110 delete _output_buffers;
114 Delivery::display_name () const
118 return _("main outs");
131 Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out)
135 /* the out buffers will be set to point to the port output buffers
136 of our output object.
140 if (_output->n_ports() != ChanCount::ZERO) {
141 /* increase number of output ports if the processor chain requires it */
142 out = ChanCount::max (_output->n_ports(), in);
145 /* not configured yet - we will passthru */
150 fatal << "programming error: this should never be reached" << endmsg;
151 abort(); /*NOTREACHED*/
155 } else if (_role == Insert) {
157 /* the output buffers will be filled with data from the *input* ports
162 if (_input->n_ports() != ChanCount::ZERO) {
163 out = _input->n_ports();
166 /* not configured yet - we will passthru */
171 fatal << "programming error: this should never be reached" << endmsg;
172 abort(); /*NOTREACHED*/
176 fatal << "programming error: this should never be reached" << endmsg;
182 /** Caller must hold process lock */
184 Delivery::configure_io (ChanCount in, ChanCount out)
187 bool r = AudioEngine::instance()->process_lock().trylock();
188 assert (!r && "trylock inside Delivery::configure_io");
191 /* check configuration by comparison with our I/O port configuration, if appropriate.
192 see ::can_support_io_configuration() for comments
198 if (_output->n_ports() != out) {
199 if (_output->n_ports() != ChanCount::ZERO) {
200 _output->ensure_io (out, false, this);
202 /* I/O not yet configured */
207 } else if (_role == Insert) {
210 if (_input->n_ports() != in) {
211 if (_input->n_ports() != ChanCount::ZERO) {
212 fatal << _name << " programming error: configure_io called with " << in << " and " << out << " with " << _input->n_ports() << " input ports" << endmsg;
213 abort(); /*NOTREACHED*/
215 /* I/O not yet configured */
222 if (!Processor::configure_io (in, out)) {
232 Delivery::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool result_required)
236 PortSet& ports (_output->ports());
239 if (!_active && !_pending_active) {
240 _output->silence (nframes);
244 /* this setup is not just for our purposes, but for anything that comes after us in the
245 processing pathway that wants to use this->output_buffers() for some reason.
248 // TODO delayline -- latency-compensation
249 output_buffers().get_backend_port_addresses (ports, nframes);
251 // this Delivery processor is not a derived type, and thus we assume
252 // we really can modify the buffers passed in (it is almost certainly
253 // the main output stage of a Route). Contrast with Send::run()
254 // which cannot do this.
256 tgain = target_gain ();
258 if (tgain != _current_gain) {
259 /* target gain has changed */
261 _current_gain = Amp::apply_gain (bufs, _session.nominal_frame_rate(), nframes, _current_gain, tgain);
263 } else if (tgain < GAIN_COEFF_SMALL) {
265 /* we were quiet last time, and we're still supposed to be quiet.
266 Silence the outputs, and make sure the buffers are quiet too,
269 _output->silence (nframes);
270 if (result_required) {
271 bufs.set_count (output_buffers().count ());
272 Amp::apply_simple_gain (bufs, nframes, GAIN_COEFF_ZERO);
276 } else if (tgain != GAIN_COEFF_UNITY) {
278 /* target gain has not changed, but is not unity */
279 Amp::apply_simple_gain (bufs, nframes, tgain);
284 if (fabs (_session.transport_speed()) > 1.5 && Config->get_quieten_at_speed ()) {
285 Amp::apply_simple_gain (bufs, nframes, speed_quietning, false);
290 if (_panshell && !_panshell->bypassed() && _panshell->panner()) {
292 // Use the panner to distribute audio to output port buffers
294 _panshell->run (bufs, output_buffers(), start_frame, end_frame, nframes);
296 // MIDI data will not have been delivered by the panner
298 if (bufs.count().n_midi() > 0 && ports.count().n_midi () > 0) {
299 _output->copy_to_outputs (bufs, DataType::MIDI, nframes, ports.port(0)->port_offset());
304 // Do a 1:1 copy of data to output ports
306 if (bufs.count().n_audio() > 0 && ports.count().n_audio () > 0) {
307 _output->copy_to_outputs (bufs, DataType::AUDIO, nframes, 0);
310 if (bufs.count().n_midi() > 0 && ports.count().n_midi () > 0) {
311 _output->copy_to_outputs (bufs, DataType::MIDI, nframes, ports.port(0)->port_offset());
315 if (result_required) {
316 bufs.read_from (output_buffers (), nframes);
320 _active = _pending_active;
324 Delivery::state (bool full_state)
326 XMLNode& node (IOProcessor::state (full_state));
329 node.add_property("type", "main-outs");
330 } else if (_role & Listen) {
331 node.add_property("type", "listen");
333 node.add_property("type", "delivery");
336 node.add_property("role", enum_2_string(_role));
339 node.add_child_nocopy (_panshell->get_state ());
340 if (_panshell->pannable()) {
341 node.add_child_nocopy (_panshell->pannable()->get_state ());
349 Delivery::set_state (const XMLNode& node, int version)
351 const XMLProperty* prop;
353 if (IOProcessor::set_state (node, version)) {
357 if ((prop = node.property ("role")) != 0) {
358 _role = Role (string_2_enum (prop->value(), _role));
359 // std::cerr << this << ' ' << _name << " set role to " << enum_2_string (_role) << std::endl;
361 // std::cerr << this << ' ' << _name << " NO ROLE INFO\n";
364 XMLNode* pan_node = node.child (X_("PannerShell"));
366 if (pan_node && _panshell) {
367 _panshell->set_state (*pan_node, version);
372 XMLNode* pannnode = node.child (X_("Pannable"));
373 if (_panshell && _panshell->panner() && pannnode) {
374 _panshell->pannable()->set_state (*pannnode, version);
383 /* caller must hold process lock */
389 Delivery::pan_outs () const
392 return _output->n_ports().n_audio();
395 return _configured_output.n_audio();
399 Delivery::reset_panner ()
402 if (!_no_panner_reset) {
404 if (_panshell && _role != Insert && _role != Listen) {
405 _panshell->configure_io (ChanCount (DataType::AUDIO, pans_required()), ChanCount (DataType::AUDIO, pan_outs()));
410 panner_legal_c.disconnect ();
411 PannersLegal.connect_same_thread (panner_legal_c, boost::bind (&Delivery::panners_became_legal, this));
416 Delivery::panners_became_legal ()
418 if (_panshell && _role != Insert) {
419 _panshell->configure_io (ChanCount (DataType::AUDIO, pans_required()), ChanCount (DataType::AUDIO, pan_outs()));
422 panner_legal_c.disconnect ();
426 Delivery::defer_pan_reset ()
428 _no_panner_reset = true;
432 Delivery::allow_pan_reset ()
434 _no_panner_reset = false;
440 Delivery::disable_panners ()
442 panners_legal = false;
447 Delivery::reset_panners ()
449 panners_legal = true;
454 Delivery::flush_buffers (framecnt_t nframes)
456 /* io_lock, not taken: function must be called from Session::process() calltree */
462 PortSet& ports (_output->ports());
464 for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
465 i->flush_buffers (nframes);
470 Delivery::transport_stopped (framepos_t now)
472 Processor::transport_stopped (now);
475 _panshell->pannable()->transport_stopped (now);
479 PortSet& ports (_output->ports());
481 for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
482 i->transport_stopped ();
488 Delivery::realtime_locate ()
491 PortSet& ports (_output->ports());
493 for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
494 i->realtime_locate ();
500 Delivery::target_gain ()
502 /* if we've been requested to deactivate, our target gain is zero */
504 if (!_pending_active) {
505 return GAIN_COEFF_ZERO;
508 /* if we've been told not to output because its a monitoring situation and
509 we're not monitoring, then be quiet.
512 if (_no_outs_cuz_we_no_monitor) {
513 return GAIN_COEFF_ZERO;
516 MuteMaster::MutePoint mp = MuteMaster::Main; // stupid gcc uninit warning
520 mp = MuteMaster::Main;
523 mp = MuteMaster::Listen;
529 mp = MuteMaster::PreFader;
531 mp = MuteMaster::PostFader;
536 gain_t desired_gain = _mute_master->mute_gain_at (mp);
538 if (_role == Listen && _session.monitor_out() && !_session.listening()) {
540 /* nobody is soloed, and this delivery is a listen-send to the
541 control/monitor/listen bus, we should be silent since
542 it gets its signal from the master out.
545 desired_gain = GAIN_COEFF_ZERO;
553 Delivery::no_outs_cuz_we_no_monitor (bool yn)
555 _no_outs_cuz_we_no_monitor = yn;
559 Delivery::set_name (const std::string& name)
561 bool ret = IOProcessor::set_name (name);
563 if (ret && _panshell) {
564 ret = _panshell->set_name (name);
570 bool ignore_output_change = false;
573 Delivery::output_changed (IOChange change, void* /*src*/)
575 if (change.type & IOChange::ConfigurationChanged) {
577 _output_buffers->attach_buffers (_output->ports ());
581 boost::shared_ptr<Panner>
582 Delivery::panner () const
585 return _panshell->panner();
587 return boost::shared_ptr<Panner>();