#include "ardour/panner.h"
#include "ardour/port.h"
#include "ardour/session.h"
+#include "ardour/audioengine.h"
#include "i18n.h"
, _current_gain (1.0)
, _output_offset (0)
, _no_outs_cuz_we_no_monitor (false)
- , _solo_level (0)
- , _solo_isolated (false)
, _mute_master (mm)
, no_panner_reset (false)
{
, _current_gain (1.0)
, _output_offset (0)
, _no_outs_cuz_we_no_monitor (false)
- , _solo_level (0)
- , _solo_isolated (false)
, _mute_master (mm)
, no_panner_reset (false)
{
CycleStart.connect_same_thread (*this, boost::bind (&Delivery::cycle_start, this, _1));
}
-/* deliver to a new IO object, reconstruct from XML */
-
-Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
- : IOProcessor (s, false, true, "reset")
- , _role (Role (0))
- , _output_buffers (new BufferSet())
- , _current_gain (1.0)
- , _output_offset (0)
- , _no_outs_cuz_we_no_monitor (false)
- , _solo_level (0)
- , _solo_isolated (false)
- , _mute_master (mm)
- , no_panner_reset (false)
-{
- _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
- _display_to_user = false;
-
- if (set_state (node, Stateful::loading_state_version)) {
- throw failed_constructor ();
- }
-
- if (_output) {
- _output->changed.connect_same_thread (*this, boost::bind (&Delivery::output_changed, this, _1, _2));
- }
-
- CycleStart.connect_same_thread (*this, boost::bind (&Delivery::cycle_start, this, _1));
-}
-
-/* deliver to an existing IO object, reconstruct from XML */
-
-Delivery::Delivery (Session& s, boost::shared_ptr<IO> out, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
- : IOProcessor (s, boost::shared_ptr<IO>(), out, "reset")
- , _role (Role (0))
- , _output_buffers (new BufferSet())
- , _current_gain (1.0)
- , _output_offset (0)
- , _no_outs_cuz_we_no_monitor (false)
- , _solo_level (0)
- , _solo_isolated (false)
- , _mute_master (mm)
- , no_panner_reset (false)
-{
- _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
- _display_to_user = false;
-
- if (set_state (node, Stateful::loading_state_version)) {
- throw failed_constructor ();
- }
-
- if (_output) {
- _output->changed.connect_same_thread (*this, boost::bind (&Delivery::output_changed, this, _1, _2));
- }
-
- CycleStart.connect_same_thread (*this, boost::bind (&Delivery::cycle_start, this, _1));
-}
Delivery::~Delivery()
{
if (_output) {
if (_output->n_ports() != ChanCount::ZERO) {
- out = _output->n_ports();
+ /* increase number of output ports if the processor chain requires it */
+ out = ChanCount::max (_output->n_ports(), in);
return true;
} else {
/* not configured yet - we will passthru */
return false;
}
+/** Caller must hold process lock */
bool
Delivery::configure_io (ChanCount in, ChanCount out)
{
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
/* check configuration by comparison with our I/O port configuration, if appropriate.
see ::can_support_io_configuration() for comments
*/
if (_output) {
if (_output->n_ports() != out) {
if (_output->n_ports() != ChanCount::ZERO) {
- fatal << _name << " programming error: configure_io with nports = " << _output->n_ports() << " called with " << in << " and " << out << " with " << _output->n_ports() << " output ports" << endmsg;
- /*NOTREACHED*/
+ _output->ensure_io (out, false, this);
} else {
/* I/O not yet configured */
}
}
}
}
- }
+ }
+
if (!Processor::configure_io (in, out)) {
return false;
}
}
void
-Delivery::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool result_required)
+Delivery::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool result_required)
{
assert (_output);
tgain = target_gain ();
if (tgain != _current_gain) {
-
/* target gain has changed */
Amp::apply_gain (bufs, nframes, _current_gain, tgain);
}
} else {
+
// Do a 1:1 copy of data to output ports
if (bufs.count().n_audio() > 0 && ports.count().n_audio () > 0) {
_output->copy_to_outputs (bufs, DataType::AUDIO, nframes, _output_offset);
- }
+ }
if (bufs.count().n_midi() > 0 && ports.count().n_midi () > 0) {
_output->copy_to_outputs (bufs, DataType::MIDI, nframes, _output_offset);
}
+
+
}
out:
void
-Delivery::start_pan_touch (uint32_t which)
+Delivery::start_pan_touch (uint32_t which, double when)
{
if (which < _panner->npanners()) {
- _panner->pan_control(which)->start_touch();
+ _panner->pan_control(which)->start_touch(when);
}
}
void
-Delivery::end_pan_touch (uint32_t which)
+Delivery::end_pan_touch (uint32_t which, bool mark, double when)
{
if (which < _panner->npanners()) {
- _panner->pan_control(which)->stop_touch();
+ _panner->pan_control(which)->stop_touch(mark, when);
}
}
-void
-Delivery::transport_stopped (sframes_t frame)
-{
- _panner->transport_stopped (frame);
-}
void
-Delivery::flush (nframes_t nframes, nframes64_t time)
+Delivery::flush_buffers (nframes_t nframes, framepos_t time)
{
/* io_lock, not taken: function must be called from Session::process() calltree */
PortSet& ports (_output->ports());
-
+
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
(*i).flush_buffers (nframes, time, _output_offset);
}
}
void
-Delivery::transport_stopped ()
+Delivery::transport_stopped (framepos_t now)
{
- /* turn off any notes that are on */
+ Processor::transport_stopped (now);
- PortSet& ports (_output->ports());
+ _panner->transport_stopped (now);
- for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
- (*i).transport_stopped ();
- }
+ if (_output) {
+ PortSet& ports (_output->ports());
+
+ for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
+ (*i).transport_stopped ();
+ }
+ }
}
gain_t
return 0.0;
}
- gain_t desired_gain;
-
-
- if (_solo_level) {
- desired_gain = 1.0;
- } else {
-
- MuteMaster::MutePoint mp;
-
- switch (_role) {
- case Main:
- mp = MuteMaster::Main;
- break;
- case Listen:
- mp = MuteMaster::Listen;
- break;
- case Send:
- case Insert:
- case Aux:
- /* XXX FIX ME this is wrong, we need per-delivery muting */
+ MuteMaster::MutePoint mp = MuteMaster::Main; // stupid gcc uninit warning
+
+ switch (_role) {
+ case Main:
+ mp = MuteMaster::Main;
+ break;
+ case Listen:
+ mp = MuteMaster::Listen;
+ break;
+ case Send:
+ case Insert:
+ case Aux:
+ if (_pre_fader) {
mp = MuteMaster::PreFader;
- break;
- }
-
- if (!_solo_isolated && _session.soloing()) {
- desired_gain = min (Config->get_solo_mute_gain(), _mute_master->mute_gain_at (mp));
-
} else {
-
- desired_gain = _mute_master->mute_gain_at (mp);
+ mp = MuteMaster::PostFader;
}
-
- }
+ break;
+ }
+
+ gain_t desired_gain = _mute_master->mute_gain_at (mp);
+
+ if (_role == Listen && _session.monitor_out() && !_session.listening()) {
+
+ /* nobody is soloed, and this delivery is a listen-send to the
+ control/monitor/listen bus, we should be silent since
+ it gets its signal from the master out.
+ */
+
+ desired_gain = 0.0;
+
+ }
return desired_gain;
}
void
Delivery::output_changed (IOChange change, void* /*src*/)
{
- if (change & ARDOUR::ConfigurationChanged) {
+ if (change.type & IOChange::ConfigurationChanged) {
reset_panner ();
}
}