+ } else if (_gain != 0 && (_phase_invert || _gain != 1.0)) {
+
+ /* no need to interpolate current gain value,
+ but its non-unity, so apply it. if the gain
+ is zero, do nothing because we'll ship silence
+ below.
+ */
+
+ gain_t this_gain;
+
+ if (_phase_invert) {
+ this_gain = -_gain;
+ } else {
+ this_gain = _gain;
+ }
+
+ for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
+ Sample* const sp = i->data();
+ apply_gain_to_buffer(sp,nframes,this_gain);
+ }
+
+ } else if (_gain == 0) {
+ for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
+ i->clear();
+ }
+ }
+ }
+
+ } else {
+
+ /* actively recording, no monitoring required; leave buffers as-is to save CPU cycles */
+
+ }
+
+ /* -------------------------------------------------------------------------------------------
+ CONTROL OUTPUT STAGE
+ ----------------------------------------------------------------------------------------- */
+
+ if ((_meter_point == MeterPostFader) && co) {
+
+ solo_audible = solo_gain > 0;
+ mute_audible = dmg > 0 || !_mute_affects_control_outs;
+
+ if ( // silent anyway
+
+ (_gain == 0 && !apply_gain_automation) ||
+
+ // muted by solo of another track
+
+ !solo_audible ||
+
+ // muted by mute of this track
+
+ !mute_audible ||
+
+ // recording but not s/w monitoring
+
+ (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording()))
+
+ ) {
+
+ co->silence (nframes);
+
+ } else {
+
+ co->deliver_output (bufs, start_frame, end_frame, nframes);
+ }
+ }
+
+ /* -------------------------------------------------------------------------------------------
+ MAIN OUTPUT STAGE
+ ----------------------------------------------------------------------------------------- */
+
+ solo_audible = dsg > 0;
+ mute_audible = dmg > 0 || !_mute_affects_main_outs;
+
+ if (n_outputs().get(_default_type) == 0) {
+
+ /* relax */
+
+ } else if (no_monitor && record_enabled()
+ && (!Config->get_auto_input() || _session.actively_recording())) {
+
+ IO::silence (nframes);
+
+ } else {
+
+ if ( // silent anyway
+
+ (_gain == 0 && !apply_gain_automation) ||
+
+ // muted by solo of another track, but not using control outs for solo
+
+ (!solo_audible && (Config->get_solo_model() != SoloBus)) ||
+
+ // muted by mute of this track
+
+ !mute_audible
+
+ ) {
+
+ /* don't use Route::silence() here, because that causes
+ all outputs (sends, port processors, etc. to be silent).
+ */
+
+ if (_meter_point == MeterPostFader) {
+ peak_meter().reset();
+ }
+
+ IO::silence (nframes);
+
+ } else {
+
+ deliver_output(bufs, start_frame, end_frame, nframes);
+
+ }
+
+ }
+}
+
+#endif /* NEW_POB */
+
+ChanCount
+Route::n_process_buffers ()
+{
+ return max (n_inputs(), processor_max_streams);
+}
+
+void
+Route::setup_peak_meters()
+{
+ ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
+ max_streams = std::max (max_streams, processor_max_streams);
+ _meter->configure_io (max_streams, max_streams);
+}
+
+void
+Route::passthru (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, int declick, bool meter_first)
+{
+ BufferSet& bufs = _session.get_scratch_buffers(n_process_buffers());
+
+ _silent = false;
+
+ collect_input (bufs, nframes);
+
+ if (meter_first) {
+ _meter->run_in_place(bufs, start_frame, end_frame, nframes);
+ meter_first = false;
+ } else {
+ meter_first = true;
+ }
+
+ process_output_buffers (bufs, start_frame, end_frame, nframes, true, declick, meter_first);
+}
+
+void
+Route::passthru_silence (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, int declick, bool meter)
+{
+ process_output_buffers (_session.get_silent_buffers (n_process_buffers()), start_frame, end_frame, nframes, true, declick, meter);
+}
+
+void
+Route::set_solo (bool yn, void *src)
+{
+ if (_solo_safe) {
+ return;
+ }
+
+ if (_mix_group && src != _mix_group && _mix_group->is_active()) {
+ _mix_group->apply (&Route::set_solo, yn, _mix_group);
+ return;
+ }
+
+ if (_soloed != yn) {
+ _soloed = yn;
+ solo_changed (src); /* EMIT SIGNAL */
+ _solo_control->Changed (); /* EMIT SIGNAL */
+ }
+
+ catch_up_on_solo_mute_override ();
+}
+
+void
+Route::catch_up_on_solo_mute_override ()
+{
+ if (Config->get_solo_model() != InverseMute) {
+ return;
+ }
+
+ {
+
+ Glib::Mutex::Lock lm (declick_lock);
+
+ if (_muted) {
+ if (Config->get_solo_mute_override()) {
+ desired_mute_gain = (_soloed?1.0:0.0);
+ } else {
+ desired_mute_gain = 0.0;
+ }
+ } else {
+ desired_mute_gain = 1.0;
+ }
+ }
+}
+
+void
+Route::set_solo_mute (bool yn)
+{
+ Glib::Mutex::Lock lm (declick_lock);
+
+ /* Called by Session in response to another Route being soloed.
+ */
+
+ desired_solo_gain = (yn?0.0:1.0);
+}
+
+void
+Route::set_solo_safe (bool yn, void *src)
+{
+ if (_solo_safe != yn) {
+ _solo_safe = yn;
+ solo_safe_changed (src); /* EMIT SIGNAL */
+ }
+}
+
+void
+Route::set_mute (bool yn, void *src)
+
+{
+ if (_mix_group && src != _mix_group && _mix_group->is_active()) {
+ _mix_group->apply (&Route::set_mute, yn, _mix_group);
+ return;
+ }
+
+ if (_muted != yn) {
+ _muted = yn;
+ mute_changed (src); /* EMIT SIGNAL */
+
+ _mute_control->Changed (); /* EMIT SIGNAL */
+
+ Glib::Mutex::Lock lm (declick_lock);
+
+ if (_soloed && Config->get_solo_mute_override()){
+ desired_mute_gain = 1.0f;
+ } else {
+ desired_mute_gain = (yn?0.0f:1.0f);
+ }
+ }
+}
+
+int
+Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err)
+{
+ ChanCount old_pms = processor_max_streams;
+
+ if (!_session.engine().connected() || !processor) {
+ return 1;
+ }
+
+ {
+ Glib::RWLock::WriterLock lm (_processor_lock);
+
+ boost::shared_ptr<PluginInsert> pi;
+ boost::shared_ptr<PortInsert> porti;
+
+ //processor->set_default_type(_default_type);
+
+ _processors.push_back (processor);
+
+ // Set up processor list channels. This will set processor->[input|output]_streams(),
+ // configure redirect ports properly, etc.
+ if (_reset_processor_counts (err)) {
+ _processors.pop_back ();
+ _reset_processor_counts (0); // it worked before we tried to add it ...
+ return -1;
+ }
+
+ if ((pi = boost::dynamic_pointer_cast<PluginInsert>(processor)) != 0) {
+
+ if (pi->natural_input_streams() == ChanCount::ZERO) {
+ /* generator plugin */
+ _have_internal_generator = true;
+ }
+
+ }
+
+ // Ensure peak vector sizes before the plugin is activated
+
+ ChanCount potential_max_streams;
+
+ potential_max_streams.set (DataType::AUDIO, max (processor->input_streams().n_audio(),
+ processor->output_streams().n_audio()));
+ potential_max_streams.set (DataType::MIDI, max (processor->input_streams().n_midi(),
+ processor->output_streams().n_midi()));
+
+ _meter->configure_io (potential_max_streams, potential_max_streams);
+
+ // XXX: do we want to emit the signal here ? change call order.
+ processor->activate ();
+ processor->ActiveChanged.connect (bind (mem_fun (_session, &Session::update_latency_compensation), false, false));
+
+ _user_latency = 0;
+ }
+
+ if (processor_max_streams != old_pms || old_pms == ChanCount::ZERO) {
+ reset_panner ();
+ }
+
+ processors_changed (); /* EMIT SIGNAL */
+
+ return 0;
+}
+
+int
+Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
+{
+ /* NOTE: this is intended to be used ONLY when copying
+ processors from another Route. Hence the subtle
+ differences between this and ::add_processor()
+ */
+
+ ChanCount old_pms = processor_max_streams;
+
+ if (!_session.engine().connected()) {
+ return 1;
+ }
+
+ {
+ Glib::RWLock::WriterLock lm (_processor_lock);
+
+ ProcessorList::iterator existing_end = _processors.end();
+ --existing_end;
+
+ ChanCount potential_max_streams;
+
+ for (ProcessorList::const_iterator i = others.begin(); i != others.end(); ++i) {
+
+ boost::shared_ptr<PluginInsert> pi;
+
+ if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
+ pi->set_count (1);
+
+ ChanCount m = max(pi->input_streams(), pi->output_streams());