X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Froute.cc;h=d0b2260c3d7094ff1e9ec1b3002f0f6752231588;hb=f5191e62578bd2ba2b3e2adf8cfc3634aa4b929c;hp=749552b0d22bad4a10a9bd2e538b6d38dd6c1929;hpb=c175baf9dd0dabbd2f4158a6e5a95486fe2f0fe0;p=ardour.git diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 749552b0d2..d0b2260c3d 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -37,6 +37,7 @@ #include "ardour/amp.h" #include "ardour/audio_buffer.h" +#include "ardour/audio_port.h" #include "ardour/audioengine.h" #include "ardour/buffer.h" #include "ardour/buffer_set.h" @@ -46,6 +47,8 @@ #include "ardour/internal_return.h" #include "ardour/internal_send.h" #include "ardour/meter.h" +#include "ardour/midi_buffer.h" +#include "ardour/midi_port.h" #include "ardour/monitor_processor.h" #include "ardour/pannable.h" #include "ardour/panner_shell.h" @@ -80,6 +83,7 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type) , _flags (flg) , _pending_declick (true) , _meter_point (MeterPostFader) + , _meter_type (MeterPeak) , _self_solo (false) , _soloed_by_others_upstream (0) , _soloed_by_others_downstream (0) @@ -94,9 +98,13 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type) , _default_type (default_type) , _remote_control_id (0) , _in_configure_processors (false) + , _initial_io_setup (false) , _custom_meter_position_noted (false) , _last_custom_meter_was_at_end (false) { + if (is_master()) { + _meter_type = MeterK20; + } processor_max_streams.reset(); } @@ -129,6 +137,7 @@ Route::init () _input->PortCountChanging.connect_same_thread (*this, boost::bind (&Route::input_port_count_changing, this, _1)); _output->changed.connect_same_thread (*this, boost::bind (&Route::output_change_handler, this, _1, _2)); + _output->PortCountChanging.connect_same_thread (*this, boost::bind (&Route::output_port_count_changing, this, _1)); /* add amp processor */ @@ -139,7 +148,7 @@ Route::init () they will be added to _processors by setup_invisible_processors () */ - _meter.reset (new PeakMeter (_session)); + _meter.reset (new PeakMeter (_session, _name)); _meter->set_display_to_user (false); _meter->activate (); @@ -158,7 +167,7 @@ Route::init () _monitor_control->activate (); } - if (is_master() || is_monitor() || is_hidden()) { + if (is_master() || is_monitor() || is_auditioner()) { _mute_master->set_solo_ignore (true); } @@ -303,9 +312,9 @@ Route::sync_order_keys (RouteSortOrderKey base) } void -Route::set_remote_control_id_from_order_key (RouteSortOrderKey key, uint32_t rid) +Route::set_remote_control_id_from_order_key (RouteSortOrderKey /*key*/, uint32_t rid) { - if (is_master() || is_monitor() || is_hidden()) { + if (is_master() || is_monitor() || is_auditioner()) { /* hard-coded remote IDs, or no remote ID */ return; } @@ -454,8 +463,8 @@ Route::process_output_buffers (BufferSet& bufs, on a transition between monitoring states we get a de-clicking gain change in the _main_outs delivery. */ - _main_outs->no_outs_cuz_we_no_monitor (monitoring_state () == MonitoringSilence); + _main_outs->no_outs_cuz_we_no_monitor (monitoring_state () == MonitoringSilence); /* ------------------------------------------------------------------------------------------- GLOBAL DECLICK (for transport changes etc.) @@ -536,11 +545,10 @@ Route::process_output_buffers (BufferSet& bufs, if (bufs.count() != (*i)->input_streams()) { DEBUG_TRACE ( DEBUG::Processors, string_compose ( - "%1 bufs = %2 input for %3 = %4\n", + "input port mismatch %1 bufs = %2 input for %3 = %4\n", _name, bufs.count(), (*i)->name(), (*i)->input_streams() ) ); - continue; } } #endif @@ -561,39 +569,26 @@ Route::n_process_buffers () } void -Route::passthru (framepos_t start_frame, framepos_t end_frame, pframes_t nframes, int declick) +Route::monitor_run (framepos_t start_frame, framepos_t end_frame, pframes_t nframes, int declick) { - BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers()); + assert (is_monitor()); + BufferSet& bufs (_session.get_route_buffers (n_process_buffers())); + passthru (bufs, start_frame, end_frame, nframes, declick); +} +void +Route::passthru (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, int declick) +{ _silent = false; - assert (bufs.available() >= input_streams()); - - if (_input->n_ports() == ChanCount::ZERO) { - silence_unlocked (nframes); - } - - bufs.set_count (input_streams()); - if (is_monitor() && _session.listening() && !_session.is_auditioning()) { /* control/monitor bus ignores input ports when something is feeding the listen "stream". data will "arrive" into the route from the intreturn processor element. */ - bufs.silence (nframes, 0); - } else { - - for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - - BufferSet::iterator o = bufs.begin(*t); - PortSet& ports (_input->ports()); - - for (PortSet::iterator i = ports.begin(*t); i != ports.end(*t); ++i, ++o) { - o->read_from (i->get_buffer(nframes), nframes); - } - } + bufs.silence (nframes, 0); } write_out_of_band_data (bufs, start_frame, end_frame, nframes); @@ -603,7 +598,7 @@ Route::passthru (framepos_t start_frame, framepos_t end_frame, pframes_t nframes void Route::passthru_silence (framepos_t start_frame, framepos_t end_frame, pframes_t nframes, int declick) { - BufferSet& bufs (_session.get_silent_buffers (n_process_buffers())); + BufferSet& bufs (_session.get_route_buffers (n_process_buffers(), true)); bufs.set_count (_input->n_ports()); write_out_of_band_data (bufs, start_frame, end_frame, nframes); @@ -789,7 +784,7 @@ Route::set_mute_master_solo () void Route::set_solo_isolated (bool yn, void *src) { - if (is_master() || is_monitor() || is_hidden()) { + if (is_master() || is_monitor() || is_auditioner()) { return; } @@ -803,7 +798,7 @@ Route::set_solo_isolated (bool yn, void *src) boost::shared_ptr routes = _session.get_routes (); for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) { - if ((*i).get() == this || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) { + if ((*i).get() == this || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) { continue; } @@ -976,7 +971,7 @@ Route::add_processor (boost::shared_ptr processor, boost::shared_ptr< DEBUG_TRACE (DEBUG::Processors, string_compose ( "%1 adding processor %2\n", name(), processor->name())); - if (!_session.engine().connected() || !processor) { + if (!AudioEngine::instance()->connected() || !processor) { return 1; } @@ -1660,7 +1655,8 @@ Route::try_configure_processors_unlocked (ChanCount in, ProcessorStreams* err) if (boost::dynamic_pointer_cast (*p)) { DEBUG_TRACE (DEBUG::Processors, "--- CONFIGURE ABORTED due to unknown processor.\n"); - break; + DEBUG_TRACE (DEBUG::Processors, "}\n"); + return list > (); } if ((*p)->can_support_io_configuration(in, out)) { @@ -1710,6 +1706,9 @@ Route::configure_processors_unlocked (ProcessorStreams* err) } ChanCount out; + bool seen_mains_out = false; + processor_out_streams = _input->n_ports(); + processor_max_streams.reset(); list< pair >::iterator c = configuration.begin(); for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++c) { @@ -1722,8 +1721,21 @@ Route::configure_processors_unlocked (ProcessorStreams* err) processor_max_streams = ChanCount::max(processor_max_streams, c->first); processor_max_streams = ChanCount::max(processor_max_streams, c->second); out = c->second; + + if (boost::dynamic_pointer_cast (*p) + && boost::dynamic_pointer_cast (*p)->role() == Delivery::Main) { + /* main delivery will increase port count to match input. + * the Delivery::Main is usually the last processor - followed only by + * 'MeterOutput'. + */ + seen_mains_out = true; + } + if (!seen_mains_out) { + processor_out_streams = out; + } } + if (_meter) { _meter->reset_max_channels (processor_max_streams); } @@ -1888,6 +1900,8 @@ Route::state(bool full_state) node->add_property("denormal-protection", _denormal_protection?"yes":"no"); node->add_property("meter-point", enum_2_string (_meter_point)); + node->add_property("meter-type", enum_2_string (_meter_type)); + if (_route_group) { node->add_property("route-group", _route_group->name()); } @@ -1952,7 +1966,7 @@ Route::state(bool full_state) boost::shared_ptr is; if ((is = boost::dynamic_pointer_cast (*i)) != 0) { - if (is->role() == Delivery::Aux || is->role() == Delivery::Listen) { + if (is->role() == Delivery::Listen) { continue; } } @@ -1999,6 +2013,7 @@ Route::set_state (const XMLNode& node, int version) } set_id (node); + _initial_io_setup = true; if ((prop = node.property (X_("flags"))) != 0) { _flags = Flag (string_2_enum (prop->value(), _flags)); @@ -2006,7 +2021,7 @@ Route::set_state (const XMLNode& node, int version) _flags = Flag (0); } - if (is_master() || is_monitor() || is_hidden()) { + if (is_master() || is_monitor() || is_auditioner()) { _mute_master->set_solo_ignore (true); } @@ -2062,6 +2077,12 @@ Route::set_state (const XMLNode& node, int version) } } + if ((prop = node.property (X_("meter-type"))) != 0) { + _meter_type = MeterType (string_2_enum (prop->value (), _meter_type)); + } + + _initial_io_setup = false; + set_processor_state (processor_state); // this looks up the internal instrument in processors @@ -2222,7 +2243,7 @@ Route::set_state_2X (const XMLNode& node, int version) _flags = Flag (0); } - if (is_master() || is_monitor() || is_hidden()) { + if (is_master() || is_monitor() || is_auditioner()) { _mute_master->set_solo_ignore (true); } @@ -2892,7 +2913,7 @@ Route::direct_feeds_according_to_graph (boost::shared_ptr other, bool* vi /** Called from the (non-realtime) butler thread when the transport is stopped */ void -Route::nonrealtime_handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool can_flush_processors) +Route::nonrealtime_handle_transport_stopped (bool /*abort_ignored*/, bool /*did_locate*/, bool can_flush_processors) { framepos_t now = _session.transport_frame(); @@ -2942,12 +2963,17 @@ void Route::output_change_handler (IOChange change, void * /*src*/) { bool need_to_queue_solo_change = true; + if (_initial_io_setup) { + return; + } if ((change.type & IOChange::ConfigurationChanged)) { /* This is called with the process lock held if change contains ConfigurationChanged */ need_to_queue_solo_change = false; + configure_processors (0); + io_changed (); /* EMIT SIGNAL */ } if (!_output->connected() && _soloed_by_others_downstream) { @@ -2985,6 +3011,7 @@ int Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool session_state_changing) { Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK); + if (!lm.locked()) { return 0; } @@ -2997,6 +3024,7 @@ Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, silence_unlocked (nframes); return 0; } + if (session_state_changing) { if (_session.transport_speed() != 0.0f) { /* we're rolling but some state is changing (e.g. our diskstream contents) @@ -3012,8 +3040,16 @@ Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, */ } + BufferSet& bufs = _session.get_route_buffers (n_process_buffers()); + + fill_buffers_with_input (bufs, _input, nframes); + + if (_meter_point == MeterInput) { + _meter->run (bufs, start_frame, end_frame, nframes, true); + } + _amp->apply_gain_automation (false); - passthru (start_frame, end_frame, nframes, 0); + passthru (bufs, start_frame, end_frame, nframes, 0); return 0; } @@ -3043,7 +3079,15 @@ Route::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, in _silent = false; - passthru (start_frame, end_frame, nframes, declick); + BufferSet& bufs = _session.get_route_buffers (n_process_buffers()); + + fill_buffers_with_input (bufs, _input, nframes); + + if (_meter_point == MeterInput) { + _meter->run (bufs, start_frame, end_frame, nframes, true); + } + + passthru (bufs, start_frame, end_frame, nframes, declick); return 0; } @@ -3072,8 +3116,6 @@ Route::flush_processors () void Route::set_meter_point (MeterPoint p, bool force) { - /* CAN BE CALLED FROM PROCESS CONTEXT */ - if (_meter_point == p && !force) { return; } @@ -3736,6 +3778,19 @@ Route::input_port_count_changing (ChanCount to) return false; } +/** Called when there is a proposed change to the output port count */ +bool +Route::output_port_count_changing (ChanCount to) +{ + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + if (processor_out_streams.get(*t) > to.get(*t)) { + return true; + } + } + /* The change is ok */ + return false; +} + list Route::unknown_processors () const { @@ -3759,13 +3814,13 @@ Route::update_port_latencies (PortSet& from, PortSet& to, bool playback, framecn universally true, but the alternative is way too corner-case to worry about. */ - jack_latency_range_t all_connections; + LatencyRange all_connections; if (from.empty()) { all_connections.min = 0; all_connections.max = 0; } else { - all_connections.min = ~((jack_nframes_t) 0); + all_connections.min = ~((pframes_t) 0); all_connections.max = 0; /* iterate over all "from" ports and determine the latency range for all of their @@ -3774,7 +3829,7 @@ Route::update_port_latencies (PortSet& from, PortSet& to, bool playback, framecn for (PortSet::iterator p = from.begin(); p != from.end(); ++p) { - jack_latency_range_t range; + LatencyRange range; p->get_connected_latency_range (range, playback); @@ -3839,7 +3894,7 @@ Route::set_public_port_latencies (framecnt_t value, bool playback) const latency compensation into account. */ - jack_latency_range_t range; + LatencyRange range; range.min = value; range.max = value; @@ -4116,6 +4171,12 @@ boost::shared_ptr Route::the_instrument () const { Glib::Threads::RWLock::WriterLock lm (_processor_lock); + return the_instrument_unlocked (); +} + +boost::shared_ptr +Route::the_instrument_unlocked () const +{ for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) { if (boost::dynamic_pointer_cast(*i)) { if ((*i)->input_streams().n_midi() > 0 && @@ -4127,6 +4188,8 @@ Route::the_instrument () const return boost::shared_ptr(); } + + void Route::non_realtime_locate (framepos_t pos) { @@ -4142,3 +4205,93 @@ Route::non_realtime_locate (framepos_t pos) } } } + +void +Route::fill_buffers_with_input (BufferSet& bufs, boost::shared_ptr io, pframes_t nframes) +{ + size_t n_buffers; + size_t i; + + /* MIDI + * + * We don't currently mix MIDI input together, so we don't need the + * complex logic of the audio case. + */ + + n_buffers = bufs.count().n_midi (); + + for (i = 0; i < n_buffers; ++i) { + + boost::shared_ptr source_port = io->midi (i); + MidiBuffer& buf (bufs.get_midi (i)); + + if (source_port) { + buf.copy (source_port->get_midi_buffer(nframes)); + } else { + buf.silence (nframes); + } + } + + /* AUDIO */ + + n_buffers = bufs.count().n_audio(); + + size_t n_ports = io->n_ports().n_audio(); + float scaling = 1.0f; + + if (n_ports > n_buffers) { + scaling = ((float) n_buffers) / n_ports; + } + + for (i = 0; i < n_ports; ++i) { + + /* if there are more ports than buffers, map them onto buffers + * in a round-robin fashion + */ + + boost::shared_ptr source_port = io->audio (i); + AudioBuffer& buf (bufs.get_audio (i%n_buffers)); + + + if (i < n_buffers) { + + /* first time through just copy a channel into + the output buffer. + */ + + buf.read_from (source_port->get_audio_buffer (nframes), nframes); + + if (scaling != 1.0f) { + buf.apply_gain (scaling, nframes); + } + + } else { + + /* on subsequent times around, merge data from + * the port with what is already there + */ + + if (scaling != 1.0f) { + buf.accumulate_with_gain_from (source_port->get_audio_buffer (nframes), nframes, 0, scaling); + } else { + buf.accumulate_from (source_port->get_audio_buffer (nframes), nframes); + } + } + } + + /* silence any remaining buffers */ + + for (; i < n_buffers; ++i) { + AudioBuffer& buf (bufs.get_audio (i)); + buf.silence (nframes); + } + + /* establish the initial setup of the buffer set, reflecting what was + copied into it. unless, of course, we are the auditioner, in which + case nothing was fed into it from the inputs at all. + */ + + if (!is_auditioner()) { + bufs.set_count (io->n_ports()); + } +}