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/enum_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"
40 DEFINE_ENUM_CONVERT(ARDOUR::Delivery::Role);
43 namespace ARDOUR { class Panner; }
47 using namespace ARDOUR;
49 PBD::Signal0<void> Delivery::PannersLegal;
50 bool Delivery::panners_legal = false;
52 /* deliver to an existing IO object */
54 Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<Pannable> pannable,
55 boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
56 : IOProcessor(s, boost::shared_ptr<IO>(), (role_requires_output_ports (r) ? io : boost::shared_ptr<IO>()), name)
58 , _output_buffers (new BufferSet())
59 , _current_gain (GAIN_COEFF_UNITY)
60 , _no_outs_cuz_we_no_monitor (false)
62 , _no_panner_reset (false)
66 if (r & (Delivery::Send|Delivery::Aux)) is_send = true;
67 _panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable, is_send));
70 _display_to_user = false;
73 _output->changed.connect_same_thread (*this, boost::bind (&Delivery::output_changed, this, _1, _2));
77 /* deliver to a new IO object */
79 Delivery::Delivery (Session& s, boost::shared_ptr<Pannable> pannable, boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
80 : IOProcessor(s, false, (role_requires_output_ports (r) ? true : false), name, "", DataType::AUDIO, (r == Send))
82 , _output_buffers (new BufferSet())
83 , _current_gain (GAIN_COEFF_UNITY)
84 , _no_outs_cuz_we_no_monitor (false)
86 , _no_panner_reset (false)
90 if (r & (Delivery::Send|Delivery::Aux)) is_send = true;
91 _panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable, is_send));
94 _display_to_user = false;
97 _output->changed.connect_same_thread (*this, boost::bind (&Delivery::output_changed, this, _1, _2));
102 Delivery::~Delivery()
104 DEBUG_TRACE (DEBUG::Destruction, string_compose ("delivery %1 destructor\n", _name));
106 /* this object should vanish from any signal callback lists
107 that it is on before we get any further. The full qualification
108 of the method name is not necessary, but is here to make it
109 clear that this call is about signals, not data flow connections.
112 ScopedConnectionList::drop_connections ();
114 delete _output_buffers;
118 Delivery::display_name () const
122 return _("main outs");
135 Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out)
139 /* the out buffers will be set to point to the port output buffers
140 of our output object.
144 if (_output->n_ports() != ChanCount::ZERO) {
145 /* increase number of output ports if the processor chain requires it */
146 out = ChanCount::max (_output->n_ports(), in);
149 /* not configured yet - we will passthru */
154 fatal << "programming error: this should never be reached" << endmsg;
155 abort(); /*NOTREACHED*/
159 } else if (_role == Insert) {
161 /* the output buffers will be filled with data from the *input* ports
166 if (_input->n_ports() != ChanCount::ZERO) {
167 out = _input->n_ports();
170 /* not configured yet - we will passthru */
175 fatal << "programming error: this should never be reached" << endmsg;
176 abort(); /*NOTREACHED*/
180 fatal << "programming error: this should never be reached" << endmsg;
186 /** Caller must hold process lock */
188 Delivery::configure_io (ChanCount in, ChanCount out)
191 bool r = AudioEngine::instance()->process_lock().trylock();
192 assert (!r && "trylock inside Delivery::configure_io");
195 /* check configuration by comparison with our I/O port configuration, if appropriate.
196 see ::can_support_io_configuration() for comments
202 if (_output->n_ports() != out) {
203 if (_output->n_ports() != ChanCount::ZERO) {
204 _output->ensure_io (out, false, this);
206 /* I/O not yet configured */
211 } else if (_role == Insert) {
214 if (_input->n_ports() != in) {
215 if (_input->n_ports() != ChanCount::ZERO) {
216 fatal << _name << " programming error: configure_io called with " << in << " and " << out << " with " << _input->n_ports() << " input ports" << endmsg;
217 abort(); /*NOTREACHED*/
219 /* I/O not yet configured */
226 if (!Processor::configure_io (in, out)) {
236 Delivery::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, double /*speed*/, pframes_t nframes, bool result_required)
240 PortSet& ports (_output->ports());
243 if (ports.num_ports () == 0) {
247 if (!_active && !_pending_active) {
248 _output->silence (nframes);
252 /* this setup is not just for our purposes, but for anything that comes after us in the
253 * processing pathway that wants to use this->output_buffers() for some reason.
256 // TODO delayline -- latency-compensation
257 output_buffers().get_backend_port_addresses (ports, nframes);
259 // this Delivery processor is not a derived type, and thus we assume
260 // we really can modify the buffers passed in (it is almost certainly
261 // the main output stage of a Route). Contrast with Send::run()
262 // which cannot do this.
264 tgain = target_gain ();
266 if (tgain != _current_gain) {
267 /* target gain has changed */
269 _current_gain = Amp::apply_gain (bufs, _session.nominal_frame_rate(), nframes, _current_gain, tgain);
271 } else if (tgain < GAIN_COEFF_SMALL) {
273 /* we were quiet last time, and we're still supposed to be quiet.
274 Silence the outputs, and make sure the buffers are quiet too,
277 _output->silence (nframes);
278 if (result_required) {
279 bufs.set_count (output_buffers().count ());
280 Amp::apply_simple_gain (bufs, nframes, GAIN_COEFF_ZERO);
284 } else if (tgain != GAIN_COEFF_UNITY) {
286 /* target gain has not changed, but is not unity */
287 Amp::apply_simple_gain (bufs, nframes, tgain);
292 if (fabs (_session.transport_speed()) > 1.5 && Config->get_quieten_at_speed ()) {
293 Amp::apply_simple_gain (bufs, nframes, speed_quietning, false);
298 if (_panshell && !_panshell->bypassed() && _panshell->panner()) {
300 // Use the panner to distribute audio to output port buffers
302 _panshell->run (bufs, output_buffers(), start_frame, end_frame, nframes);
304 // non-audio data will not have been delivered by the panner
306 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
307 if (*t != DataType::AUDIO && bufs.count().get(*t) > 0) {
308 _output->copy_to_outputs (bufs, *t, nframes, Port::port_offset());
314 /* Do a 1:1 copy of data to output ports
316 Audio is handled separately because we use 0 for the offset,
317 since the port offset is only used for timestamped events
321 if (bufs.count().n_audio() > 0) {
322 _output->copy_to_outputs (bufs, DataType::AUDIO, nframes, 0);
325 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
326 if (*t != DataType::AUDIO && bufs.count().get(*t) > 0) {
327 _output->copy_to_outputs (bufs, *t, nframes, Port::port_offset());
332 if (result_required) {
333 /* "bufs" are internal, meaning they should never reflect
334 split-cycle offsets. So shift events back in time from where
335 they were for the external buffers associated with Ports.
338 const BufferSet& outs (output_buffers());
339 bufs.set_count (output_buffers().count ());
341 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
344 for (BufferSet::iterator b = bufs.begin (*t); b != bufs.end (*t); ++b) {
345 if (outs.count ().get (*t) <= n) {
348 b->read_from (outs.get (*t, n++), nframes, (*t == DataType::AUDIO ? 0 : -Port::port_offset()));
354 _active = _pending_active;
358 Delivery::state (bool full_state)
360 XMLNode& node (IOProcessor::state (full_state));
363 node.set_property("type", "main-outs");
364 } else if (_role & Listen) {
365 node.set_property("type", "listen");
367 node.set_property("type", "delivery");
370 node.set_property("role", _role);
373 node.add_child_nocopy (_panshell->get_state ());
374 if (_panshell->pannable()) {
375 node.add_child_nocopy (_panshell->pannable()->get_state ());
383 Delivery::set_state (const XMLNode& node, int version)
385 if (IOProcessor::set_state (node, version)) {
389 if (node.get_property ("role", _role)) {
390 // std::cerr << this << ' ' << _name << " set role to " << enum_2_string (_role) << std::endl;
392 // std::cerr << this << ' ' << _name << " NO ROLE INFO\n";
395 XMLNode* pan_node = node.child (X_("PannerShell"));
397 if (pan_node && _panshell) {
398 _panshell->set_state (*pan_node, version);
403 XMLNode* pannnode = node.child (X_("Pannable"));
404 if (_panshell && _panshell->panner() && pannnode) {
405 _panshell->pannable()->set_state (*pannnode, version);
414 /* caller must hold process lock */
420 Delivery::pan_outs () const
423 return _output->n_ports().n_audio();
426 return _configured_output.n_audio();
430 Delivery::reset_panner ()
433 if (!_no_panner_reset) {
435 if (_panshell && _role != Insert && _role != Listen) {
436 _panshell->configure_io (ChanCount (DataType::AUDIO, pans_required()), ChanCount (DataType::AUDIO, pan_outs()));
441 panner_legal_c.disconnect ();
442 PannersLegal.connect_same_thread (panner_legal_c, boost::bind (&Delivery::panners_became_legal, this));
447 Delivery::panners_became_legal ()
449 if (_panshell && _role != Insert) {
450 _panshell->configure_io (ChanCount (DataType::AUDIO, pans_required()), ChanCount (DataType::AUDIO, pan_outs()));
453 panner_legal_c.disconnect ();
457 Delivery::defer_pan_reset ()
459 _no_panner_reset = true;
463 Delivery::allow_pan_reset ()
465 _no_panner_reset = false;
471 Delivery::disable_panners ()
473 panners_legal = false;
478 Delivery::reset_panners ()
480 panners_legal = true;
485 Delivery::flush_buffers (framecnt_t nframes)
487 /* io_lock, not taken: function must be called from Session::process() calltree */
493 PortSet& ports (_output->ports());
495 for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
496 i->flush_buffers (nframes);
501 Delivery::non_realtime_transport_stop (framepos_t now, bool flush)
503 Processor::non_realtime_transport_stop (now, flush);
506 _panshell->pannable()->non_realtime_transport_stop (now, flush);
510 PortSet& ports (_output->ports());
512 for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
513 i->transport_stopped ();
519 Delivery::realtime_locate ()
522 PortSet& ports (_output->ports());
524 for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
525 i->realtime_locate ();
531 Delivery::target_gain ()
533 /* if we've been requested to deactivate, our target gain is zero */
535 if (!_pending_active) {
536 return GAIN_COEFF_ZERO;
539 /* if we've been told not to output because its a monitoring situation and
540 we're not monitoring, then be quiet.
543 if (_no_outs_cuz_we_no_monitor) {
544 return GAIN_COEFF_ZERO;
547 MuteMaster::MutePoint mp = MuteMaster::Main; // stupid gcc uninit warning
551 mp = MuteMaster::Main;
554 mp = MuteMaster::Listen;
560 mp = MuteMaster::PreFader;
562 mp = MuteMaster::PostFader;
567 gain_t desired_gain = _mute_master->mute_gain_at (mp);
569 if (_role == Listen && _session.monitor_out() && !_session.listening()) {
571 /* nobody is soloed, and this delivery is a listen-send to the
572 * control/monitor/listen bus, we should be silent since
573 * it gets its signal from the master out.
576 desired_gain = GAIN_COEFF_ZERO;
583 Delivery::no_outs_cuz_we_no_monitor (bool yn)
585 _no_outs_cuz_we_no_monitor = yn;
589 Delivery::set_name (const std::string& name)
591 bool ret = IOProcessor::set_name (name);
593 if (ret && _panshell) {
594 ret = _panshell->set_name (name);
600 bool ignore_output_change = false;
603 Delivery::output_changed (IOChange change, void* /*src*/)
605 if (change.type & IOChange::ConfigurationChanged) {
607 _output_buffers->attach_buffers (_output->ports ());
611 boost::shared_ptr<Panner>
612 Delivery::panner () const
615 return _panshell->panner();
617 return boost::shared_ptr<Panner>();