X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Froute.cc;h=5c4be739793295de55f988afbb97f1eda77103fa;hb=1bd4c5b3a212460eed1773f6b049d18c89625565;hp=7f7b56cc2bbea152ae3a13916b46b3d388e8177f;hpb=94ba45c0571e6822268edf0ea3279901d0b93e63;p=ardour.git diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 7f7b56cc2b..5c4be73979 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -20,11 +20,13 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -44,25 +46,25 @@ using namespace std; using namespace ARDOUR; -//using namespace sigc; +using namespace PBD; uint32_t Route::order_key_cnt = 0; -Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg) - : IO (sess, name, input_min, input_max, output_min, output_max), +Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type) + : IO (sess, name, input_min, input_max, output_min, output_max, default_type), _flags (flg), - _midi_solo_control (*this, MIDIToggleControl::SoloControl, _session.midi_port()), - _midi_mute_control (*this, MIDIToggleControl::MuteControl, _session.midi_port()) + _solo_control (X_("solo"), *this, ToggleControllable::SoloControl), + _mute_control (X_("mute"), *this, ToggleControllable::MuteControl) { init (); } Route::Route (Session& sess, const XMLNode& node) : IO (sess, "route"), - _midi_solo_control (*this, MIDIToggleControl::SoloControl, _session.midi_port()), - _midi_mute_control (*this, MIDIToggleControl::MuteControl, _session.midi_port()) + _solo_control (X_("solo"), *this, ToggleControllable::SoloControl), + _mute_control (X_("mute"), *this, ToggleControllable::MuteControl) { init (); set_state (node); @@ -87,7 +89,8 @@ Route::init () _declickable = false; _pending_declick = true; _remote_control_id = 0; - + _ignore_gain_on_deliver = true; + _edit_group = 0; _mix_group = 0; @@ -105,13 +108,10 @@ Route::init () input_changed.connect (mem_fun (this, &Route::input_change_handler)); output_changed.connect (mem_fun (this, &Route::output_change_handler)); - - reset_midi_control (_session.midi_port(), _session.get_midi_control()); } Route::~Route () { - GoingAway (); /* EMIT SIGNAL */ clear_redirects (this); if (_control_outs) { @@ -216,8 +216,8 @@ Route::set_gain (gain_t val, void *src) void Route::process_output_buffers (vector& bufs, uint32_t nbufs, - jack_nframes_t start_frame, jack_nframes_t end_frame, - jack_nframes_t nframes, jack_nframes_t offset, bool with_redirects, int declick, + nframes_t start_frame, nframes_t end_frame, + nframes_t nframes, nframes_t offset, bool with_redirects, int declick, bool meter) { uint32_t n; @@ -229,13 +229,22 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, IO *co; bool mute_audible; bool solo_audible; - bool no_monitor = (Config->get_use_hardware_monitoring() || !Config->get_use_sw_monitoring ()); + bool no_monitor; gain_t* gab = _session.gain_automation_buffer(); + switch (Config->get_monitoring_model()) { + case HardwareMonitoring: + case ExternalMonitoring: + no_monitor = true; + break; + default: + no_monitor = false; + } + declick = _pending_declick; { - TentativeLockMonitor cm (control_outs_lock, __LINE__, __FILE__); + Glib::Mutex::Lock cm (control_outs_lock, Glib::TRY_LOCK); if (cm.locked()) { co = _control_outs; @@ -245,7 +254,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, } { - TentativeLockMonitor dm (declick_lock, __LINE__, __FILE__); + Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK); if (dm.locked()) { dmg = desired_mute_gain; @@ -263,17 +272,17 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, -------------------------------------------------------------------------------------------------- */ if (declick > 0) { - apply_declick (bufs, nbufs, nframes, 0.0, 1.0, _phase_invert); + apply_declick (bufs, nbufs, nframes, 0.0, 1.0, false); _pending_declick = 0; } else if (declick < 0) { - apply_declick (bufs, nbufs, nframes, 1.0, 0.0, _phase_invert); + apply_declick (bufs, nbufs, nframes, 1.0, 0.0, false); _pending_declick = 0; } else { /* no global declick */ if (solo_gain != dsg) { - apply_declick (bufs, nbufs, nframes, solo_gain, dsg, _phase_invert); + apply_declick (bufs, nbufs, nframes, solo_gain, dsg, false); solo_gain = dsg; } } @@ -290,7 +299,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, } if (!_soloed && _mute_affects_pre_fader && (mute_gain != dmg)) { - apply_declick (bufs, nbufs, nframes, mute_gain, dmg, _phase_invert); + apply_declick (bufs, nbufs, nframes, mute_gain, dmg, false); mute_gain = dmg; mute_declick_applied = true; } @@ -312,7 +321,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, // TODO: this is probably wrong - (no_monitor && record_enabled() && (!_session.get_auto_input() || _session.actively_recording())) + (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) ) { @@ -330,7 +339,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, -------------------------------------------------------------------------------------------------- */ if (with_redirects) { - TentativeRWLockMonitor rm (redirect_lock, false, __LINE__, __FILE__); + Glib::RWLock::ReaderLock rm (redirect_lock, Glib::TRY_LOCK); if (rm.locked()) { if (mute_gain > 0 || !_mute_affects_pre_fader) { for (i = _redirects.begin(); i != _redirects.end(); ++i) { @@ -360,7 +369,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_post_fader) { - apply_declick (bufs, nbufs, nframes, mute_gain, dmg, _phase_invert); + apply_declick (bufs, nbufs, nframes, mute_gain, dmg, false); mute_gain = dmg; mute_declick_applied = true; } @@ -391,7 +400,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, // rec-enabled but not s/w monitoring - (no_monitor && record_enabled() && (!_session.get_auto_input() || _session.actively_recording())) + (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) ) { @@ -418,11 +427,11 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, // h/w monitoring not in use - (!Config->get_use_hardware_monitoring() && + (!Config->get_monitoring_model() == HardwareMonitoring && // AND software monitoring required - Config->get_use_sw_monitoring())) { + Config->get_monitoring_model() == SoftwareMonitoring)) { if (apply_gain_automation) { @@ -430,7 +439,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, for (n = 0; n < nbufs; ++n) { Sample *sp = bufs[n]; - for (jack_nframes_t nx = 0; nx < nframes; ++nx) { + for (nframes_t nx = 0; nx < nframes; ++nx) { sp[nx] *= -gab[nx]; } } @@ -438,7 +447,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, for (n = 0; n < nbufs; ++n) { Sample *sp = bufs[n]; - for (jack_nframes_t nx = 0; nx < nframes; ++nx) { + for (nframes_t nx = 0; nx < nframes; ++nx) { sp[nx] *= gab[nx]; } } @@ -475,7 +484,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, for (n = 0; n < nbufs; ++n) { Sample *sp = bufs[n]; - apply_gain_to_buffer(sp,nframes,this_gain); + Session::apply_gain_to_buffer(sp,nframes,this_gain); } } else if (_gain == 0) { @@ -499,7 +508,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, if (post_fader_work) { - TentativeRWLockMonitor rm (redirect_lock, false, __LINE__, __FILE__); + Glib::RWLock::ReaderLock rm (redirect_lock, Glib::TRY_LOCK); if (rm.locked()) { if (mute_gain > 0 || !_mute_affects_post_fader) { for (i = _redirects.begin(); i != _redirects.end(); ++i) { @@ -526,7 +535,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, } if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_control_outs) { - apply_declick (bufs, nbufs, nframes, mute_gain, dmg, _phase_invert); + apply_declick (bufs, nbufs, nframes, mute_gain, dmg, false); mute_gain = dmg; mute_declick_applied = true; } @@ -539,7 +548,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, solo_audible = solo_gain > 0; mute_audible = dmg > 0 || !_mute_affects_control_outs; - + if ( // silent anyway (_gain == 0 && !apply_gain_automation) || @@ -554,7 +563,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, // recording but not s/w monitoring - (no_monitor && record_enabled() && (!_session.get_auto_input() || _session.actively_recording())) + (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) ) { @@ -571,7 +580,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, ----------------------------------------------------------------------*/ if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_main_outs) { - apply_declick (bufs, nbufs, nframes, mute_gain, dmg, _phase_invert); + apply_declick (bufs, nbufs, nframes, mute_gain, dmg, false); mute_gain = dmg; mute_declick_applied = true; } @@ -587,7 +596,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, /* relax */ - } else if (no_monitor && record_enabled() && (!_session.get_auto_input() || _session.actively_recording())) { + } else if (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) { IO::silence (nframes, offset); @@ -599,7 +608,7 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, // muted by solo of another track, but not using control outs for solo - (!solo_audible && (_session.solo_model() != Session::SoloBus)) || + (!solo_audible && (Config->get_solo_model() != SoloBus)) || // muted by mute of this track @@ -619,9 +628,12 @@ Route::process_output_buffers (vector& bufs, uint32_t nbufs, } else { - if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) { + if ((_session.transport_speed() > 1.5f || + _session.transport_speed() < -1.5f) && + Config->get_quieten_at_speed()) { pan (bufs, nbufs, nframes, offset, speed_quietning); } else { + // cerr << _name << " panner state = " << _panner->automation_state() << endl; if (!_panner->empty() && (_panner->automation_state() & Play || ((_panner->automation_state() & Touch) && !_panner->touching()))) { @@ -663,7 +675,7 @@ Route::n_process_buffers () void -Route::passthru (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter_first) +Route::passthru (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset, int declick, bool meter_first) { vector& bufs = _session.get_passthru_buffers(); uint32_t limit = n_process_buffers (); @@ -711,18 +723,15 @@ Route::set_solo (bool yn, void *src) if (_soloed != yn) { _soloed = yn; - solo_changed (src); /* EMIT SIGNAL */ - - if (_session.get_midi_feedback()) { - _midi_solo_control.send_feedback (_soloed); - } + solo_changed (src); /* EMIT SIGNAL */ + _solo_control.Changed (); /* EMIT SIGNAL */ } } void Route::set_solo_mute (bool yn) { - LockMonitor lm (declick_lock, __LINE__, __FILE__); + Glib::Mutex::Lock lm (declick_lock); /* Called by Session in response to another Route being soloed. */ @@ -752,17 +761,15 @@ Route::set_mute (bool yn, void *src) _muted = yn; mute_changed (src); /* EMIT SIGNAL */ - if (_session.get_midi_feedback()) { - _midi_mute_control.send_feedback (_muted); - } + _mute_control.Changed (); /* EMIT SIGNAL */ - LockMonitor lm (declick_lock, __LINE__, __FILE__); + Glib::Mutex::Lock lm (declick_lock); desired_mute_gain = (yn?0.0f:1.0f); } } int -Route::add_redirect (Redirect *redirect, void *src, uint32_t* err_streams) +Route::add_redirect (boost::shared_ptr redirect, void *src, uint32_t* err_streams) { uint32_t old_rmo = redirect_max_outs; @@ -771,14 +778,14 @@ Route::add_redirect (Redirect *redirect, void *src, uint32_t* err_streams) } { - RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__); + Glib::RWLock::WriterLock lm (redirect_lock); - PluginInsert* pi; - PortInsert* porti; + boost::shared_ptr pi; + boost::shared_ptr porti; uint32_t potential_max_streams = 0; - if ((pi = dynamic_cast(redirect)) != 0) { + if ((pi = boost::dynamic_pointer_cast(redirect)) != 0) { pi->set_count (1); if (pi->input_streams() == 0) { @@ -787,8 +794,8 @@ Route::add_redirect (Redirect *redirect, void *src, uint32_t* err_streams) } potential_max_streams = max(pi->input_streams(), pi->output_streams()); - - } else if ((porti = dynamic_cast(redirect)) != 0) { + + } else if ((porti = boost::dynamic_pointer_cast(redirect)) != 0) { /* force new port inserts to start out with an i/o configuration that matches this route's i/o configuration. @@ -809,8 +816,8 @@ Route::add_redirect (Redirect *redirect, void *src, uint32_t* err_streams) while (_peak_power.size() < potential_max_streams) { _peak_power.push_back(0); } - while (_stored_peak_power.size() < potential_max_streams) { - _stored_peak_power.push_back(0); + while (_visible_peak_power.size() < potential_max_streams) { + _visible_peak_power.push_back(0); } _redirects.push_back (redirect); @@ -844,7 +851,7 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea } { - RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__); + Glib::RWLock::WriterLock lm (redirect_lock); RedirectList::iterator existing_end = _redirects.end(); --existing_end; @@ -853,9 +860,9 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea for (RedirectList::const_iterator i = others.begin(); i != others.end(); ++i) { - PluginInsert* pi; + boost::shared_ptr pi; - if ((pi = dynamic_cast(*i)) != 0) { + if ((pi = boost::dynamic_pointer_cast(*i)) != 0) { pi->set_count (1); uint32_t m = max(pi->input_streams(), pi->output_streams()); @@ -867,8 +874,8 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea while (_peak_power.size() < potential_max_streams) { _peak_power.push_back(0); } - while (_stored_peak_power.size() < potential_max_streams) { - _stored_peak_power.push_back(0); + while (_visible_peak_power.size() < potential_max_streams) { + _visible_peak_power.push_back(0); } _redirects.push_back (*i); @@ -903,12 +910,7 @@ Route::clear_redirects (void *src) } { - RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__); - - for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { - delete *i; - } - + Glib::RWLock::WriterLock lm (redirect_lock); _redirects.clear (); } @@ -922,7 +924,7 @@ Route::clear_redirects (void *src) } int -Route::remove_redirect (Redirect *redirect, void *src, uint32_t* err_streams) +Route::remove_redirect (boost::shared_ptr redirect, void *src, uint32_t* err_streams) { uint32_t old_rmo = redirect_max_outs; @@ -933,7 +935,7 @@ Route::remove_redirect (Redirect *redirect, void *src, uint32_t* err_streams) redirect_max_outs = 0; { - RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__); + Glib::RWLock::WriterLock lm (redirect_lock); RedirectList::iterator i; bool removed = false; @@ -954,13 +956,13 @@ Route::remove_redirect (Redirect *redirect, void *src, uint32_t* err_streams) run. */ - Send* send; - PortInsert* port_insert; + boost::shared_ptr send; + boost::shared_ptr port_insert; - if ((send = dynamic_cast (*i)) != 0) { + if ((send = boost::dynamic_pointer_cast (*i)) != 0) { send->disconnect_inputs (this); send->disconnect_outputs (this); - } else if ((port_insert = dynamic_cast (*i)) != 0) { + } else if ((port_insert = boost::dynamic_pointer_cast (*i)) != 0) { port_insert->disconnect_inputs (this); port_insert->disconnect_outputs (this); } @@ -989,9 +991,9 @@ Route::remove_redirect (Redirect *redirect, void *src, uint32_t* err_streams) bool foo = false; for (i = _redirects.begin(); i != _redirects.end(); ++i) { - PluginInsert* pi; - - if ((pi = dynamic_cast(*i)) != 0) { + boost::shared_ptr pi; + + if ((pi = boost::dynamic_pointer_cast(*i)) != 0) { if (pi->is_generator()) { foo = true; } @@ -1012,7 +1014,7 @@ Route::remove_redirect (Redirect *redirect, void *src, uint32_t* err_streams) int Route::reset_plugin_counts (uint32_t* lpc) { - RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__); + Glib::RWLock::WriterLock lm (redirect_lock); return _reset_plugin_counts (lpc); } @@ -1024,7 +1026,7 @@ Route::_reset_plugin_counts (uint32_t* err_streams) uint32_t i_cnt; uint32_t s_cnt; map > insert_map; - jack_nframes_t initial_streams; + nframes_t initial_streams; redirect_max_outs = 0; i_cnt = 0; @@ -1038,7 +1040,7 @@ Route::_reset_plugin_counts (uint32_t* err_streams) for (r = _redirects.begin(); r != _redirects.end(); ++r) { - Insert *insert; + boost::shared_ptr insert; /* do this here in case we bomb out before we get to the end of this function. @@ -1046,22 +1048,22 @@ Route::_reset_plugin_counts (uint32_t* err_streams) redirect_max_outs = max ((*r)->output_streams (), redirect_max_outs); - if ((insert = dynamic_cast(*r)) != 0) { + if ((insert = boost::dynamic_pointer_cast(*r)) != 0) { ++i_cnt; - insert_map[insert->placement()].push_back (InsertCount (*insert)); + insert_map[insert->placement()].push_back (InsertCount (insert)); /* reset plugin counts back to one for now so that we have a predictable, controlled state to try to configure. */ - PluginInsert* pi; + boost::shared_ptr pi; - if ((pi = dynamic_cast(insert)) != 0) { + if ((pi = boost::dynamic_pointer_cast(insert)) != 0) { pi->set_count (1); } - } else if (dynamic_cast (*r) != 0) { + } else if (boost::dynamic_pointer_cast (*r) != 0) { ++s_cnt; } } @@ -1088,7 +1090,7 @@ Route::_reset_plugin_counts (uint32_t* err_streams) if (!insert_map[PreFader].empty()) { InsertCount& ic (insert_map[PreFader].back()); - initial_streams = ic.insert.compute_output_streams (ic.cnt); + initial_streams = ic.insert->compute_output_streams (ic.cnt); } else { initial_streams = n_inputs (); } @@ -1112,9 +1114,9 @@ Route::_reset_plugin_counts (uint32_t* err_streams) RedirectList::iterator prev = _redirects.end(); for (r = _redirects.begin(); r != _redirects.end(); prev = r, ++r) { - Send* s; + boost::shared_ptr s; - if ((s = dynamic_cast (*r)) != 0) { + if ((s = boost::dynamic_pointer_cast (*r)) != 0) { if (r == _redirects.begin()) { s->expect_inputs (n_inputs()); } else { @@ -1137,11 +1139,11 @@ Route::apply_some_plugin_counts (list& iclist) for (i = iclist.begin(); i != iclist.end(); ++i) { - if ((*i).insert.configure_io ((*i).cnt, (*i).in, (*i).out)) { + if ((*i).insert->configure_io ((*i).cnt, (*i).in, (*i).out)) { return -1; } /* make sure that however many we have, they are all active */ - (*i).insert.activate (); + (*i).insert->activate (); } return 0; @@ -1154,7 +1156,7 @@ Route::check_some_plugin_counts (list& iclist, int32_t required_inp for (i = iclist.begin(); i != iclist.end(); ++i) { - if (((*i).cnt = (*i).insert.can_support_input_configuration (required_inputs)) < 0) { + if (((*i).cnt = (*i).insert->can_support_input_configuration (required_inputs)) < 0) { if (err_streams) { *err_streams = required_inputs; } @@ -1162,7 +1164,7 @@ Route::check_some_plugin_counts (list& iclist, int32_t required_inp } (*i).in = required_inputs; - (*i).out = (*i).insert.compute_output_streams ((*i).cnt); + (*i).out = (*i).insert->compute_output_streams ((*i).cnt); required_inputs = (*i).out; } @@ -1182,7 +1184,7 @@ Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_st RedirectList to_be_deleted; { - RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__); + Glib::RWLock::WriterLock lm (redirect_lock); RedirectList::iterator tmp; RedirectList the_copy; @@ -1206,7 +1208,7 @@ Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_st for (RedirectList::const_iterator i = other._redirects.begin(); i != other._redirects.end(); ++i) { if ((*i)->placement() == placement) { - _redirects.push_back (Redirect::clone (**i)); + _redirects.push_back (Redirect::clone (*i)); } } @@ -1224,7 +1226,6 @@ Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_st ++tmp; if ((*i)->placement() == placement) { - delete *i; _redirects.erase (i); } @@ -1243,10 +1244,7 @@ Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_st } else { /* SUCCESSFUL COPY ATTEMPT: delete the redirects we removed pre-copy */ - - for (RedirectList::iterator i = to_be_deleted.begin(); i != to_be_deleted.end(); ++i) { - delete *i; - } + to_be_deleted.clear (); } } @@ -1261,7 +1259,7 @@ Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_st void Route::all_redirects_flip () { - RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__); + Glib::RWLock::ReaderLock lm (redirect_lock); if (_redirects.empty()) { return; @@ -1277,7 +1275,7 @@ Route::all_redirects_flip () void Route::all_redirects_active (bool state) { - RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__); + Glib::RWLock::ReaderLock lm (redirect_lock); if (_redirects.empty()) { return; @@ -1289,7 +1287,7 @@ Route::all_redirects_active (bool state) } struct RedirectSorter { - bool operator() (const Redirect *a, const Redirect *b) { + bool operator() (boost::shared_ptr a, boost::shared_ptr b) { return a->sort_key() < b->sort_key(); } }; @@ -1299,7 +1297,7 @@ Route::sort_redirects (uint32_t* err_streams) { { RedirectSorter comparator; - RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__); + Glib::RWLock::WriterLock lm (redirect_lock); uint32_t old_rmo = redirect_max_outs; /* the sweet power of C++ ... */ @@ -1337,7 +1335,6 @@ XMLNode& Route::state(bool full_state) { XMLNode *node = new XMLNode("Route"); - XMLNode *aevents; RedirectList:: iterator i; char buf[32]; @@ -1345,6 +1342,9 @@ Route::state(bool full_state) snprintf (buf, sizeof (buf), "0x%x", _flags); node->add_property("flags", buf); } + + node->add_property("default-type", _default_type.to_string()); + node->add_property("active", _active?"yes":"no"); node->add_property("muted", _muted?"yes":"no"); node->add_property("soloed", _soloed?"yes":"no"); @@ -1361,26 +1361,6 @@ Route::state(bool full_state) node->add_property("mix-group", _mix_group->name()); } - /* MIDI control */ - - MIDI::channel_t chn; - MIDI::eventType ev; - MIDI::byte additional; - XMLNode* midi_node = 0; - XMLNode* child; - - midi_node = node->add_child ("MIDI"); - - if (_midi_mute_control.get_control_info (chn, ev, additional)) { - child = midi_node->add_child ("mute"); - set_midi_node_info (child, ev, chn, additional); - } - if (_midi_solo_control.get_control_info (chn, ev, additional)) { - child = midi_node->add_child ("solo"); - set_midi_node_info (child, ev, chn, additional); - } - - string order_string; OrderKeys::iterator x = order_keys.begin(); @@ -1401,6 +1381,8 @@ Route::state(bool full_state) node->add_property ("order-keys", order_string); node->add_child_nocopy (IO::state (full_state)); + node->add_child_nocopy (_solo_control.get_state ()); + node->add_child_nocopy (_mute_control.get_state ()); if (_control_outs) { XMLNode* cnode = new XMLNode (X_("ControlOuts")); @@ -1413,26 +1395,6 @@ Route::state(bool full_state) cmt->add_content (_comment); } - if (full_state) { - string path; - - path = _session.snap_name(); - path += "-gain-"; - path += legalize_for_path (_name); - path += ".automation"; - - /* XXX we didn't ask for a state save, we asked for the current state. - FIX ME! - */ - - if (save_automation (path)) { - error << _("Could not get state of route. Problem with save_automation") << endmsg; - } - - aevents = node->add_child ("Automation"); - aevents->add_property ("path", path); - } - for (i = _redirects.begin(); i != _redirects.end(); ++i) { node->add_child_nocopy((*i)->state (full_state)); } @@ -1468,13 +1430,13 @@ void Route::add_redirect_from_xml (const XMLNode& node) { const XMLProperty *prop; - Insert *insert = 0; - Send *send = 0; if (node.name() == "Send") { + try { - send = new Send (_session, node); + boost::shared_ptr send (new Send (_session, node)); + add_redirect (send, this); } catch (failed_constructor &err) { @@ -1482,21 +1444,21 @@ Route::add_redirect_from_xml (const XMLNode& node) return; } - add_redirect (send, this); - } else if (node.name() == "Insert") { try { if ((prop = node.property ("type")) != 0) { + boost::shared_ptr insert; + if (prop->value() == "ladspa" || prop->value() == "Ladspa" || prop->value() == "vst") { - insert = new PluginInsert(_session, node); + insert.reset (new PluginInsert(_session, node)); } else if (prop->value() == "port") { - insert = new PortInsert (_session, node); + insert.reset (new PortInsert (_session, node)); } else { @@ -1525,8 +1487,6 @@ Route::set_state (const XMLNode& node) XMLNode *child; XMLPropertyList plist; const XMLProperty *prop; - XMLNodeList midi_kids; - if (node.name() != "Route"){ error << string_compose(_("Bad node sent to Route::set_state() [%1]"), node.name()) << endmsg; @@ -1540,6 +1500,11 @@ Route::set_state (const XMLNode& node) } else { _flags = Flag (0); } + + if ((prop = node.property ("default-type")) != 0) { + _default_type = DataType(prop->value()); + assert(_default_type != DataType::NIL); + } if ((prop = node.property ("phase-invert")) != 0) { set_phase_invert(prop->value()=="yes"?true:false, this); @@ -1672,20 +1637,6 @@ Route::set_state (const XMLNode& node) add_redirect_from_xml (*child); } - } else if (child->name() == "Automation") { - - XMLPropertyList plist; - XMLPropertyConstIterator piter; - XMLProperty *prop; - - plist = child->properties(); - for (piter = plist.begin(); piter != plist.end(); ++piter) { - prop = *piter; - if (prop->name() == "path") { - load_automation (prop->value()); - } - } - } else if (child->name() == "ControlOuts") { string coutname = _name; @@ -1703,6 +1654,12 @@ Route::set_state (const XMLNode& node) } else if (child->name() == "extra") { _extra_xml = new XMLNode (*child); + } else if (child->name() == "solo") { + _solo_control.set_state (*child); + _session.add_controllable (&_solo_control); + } else if (child->name() == "mute") { + _mute_control.set_state (*child); + _session.add_controllable (&_mute_control); } } @@ -1715,45 +1672,6 @@ Route::set_state (const XMLNode& node) } } - midi_kids = node.children ("MIDI"); - - for (niter = midi_kids.begin(); niter != midi_kids.end(); ++niter) { - - XMLNodeList kids; - XMLNodeConstIterator miter; - XMLNode* child; - - kids = (*niter)->children (); - - for (miter = kids.begin(); miter != kids.end(); ++miter) { - - child =* miter; - - MIDI::eventType ev = MIDI::on; /* initialize to keep gcc happy */ - MIDI::byte additional = 0; /* ditto */ - MIDI::channel_t chn = 0; /* ditto */ - - if (child->name() == "mute") { - - if (get_midi_node_info (child, ev, chn, additional)) { - _midi_mute_control.set_control_type (chn, ev, additional); - } else { - error << string_compose(_("MIDI mute control specification for %1 is incomplete, so it has been ignored"), _name) << endmsg; - } - } - else if (child->name() == "solo") { - - if (get_midi_node_info (child, ev, chn, additional)) { - _midi_solo_control.set_control_type (chn, ev, additional); - } else { - error << string_compose(_("MIDI mute control specification for %1 is incomplete, so it has been ignored"), _name) << endmsg; - } - } - - } - } - - return 0; } @@ -1765,7 +1683,7 @@ Route::curve_reallocate () } void -Route::silence (jack_nframes_t nframes, jack_nframes_t offset) +Route::silence (nframes_t nframes, nframes_t offset) { if (!_silent) { @@ -1778,12 +1696,12 @@ Route::silence (jack_nframes_t nframes, jack_nframes_t offset) } { - TentativeRWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__); + Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK); if (lm.locked()) { for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { - PluginInsert* pi; - if (!_active && (pi = dynamic_cast (*i)) != 0) { + boost::shared_ptr pi; + if (!_active && (pi = boost::dynamic_pointer_cast (*i)) != 0) { // skip plugins, they don't need anything when we're not active continue; } @@ -1803,7 +1721,7 @@ Route::silence (jack_nframes_t nframes, jack_nframes_t offset) int Route::set_control_outs (const vector& ports) { - LockMonitor lm (control_outs_lock, __LINE__, __FILE__); + Glib::Mutex::Lock lm (control_outs_lock); vector::const_iterator i; if (_control_outs) { @@ -1833,16 +1751,27 @@ void Route::set_edit_group (RouteGroup *eg, void *src) { + if (eg == _edit_group) { + return; + } + if (_edit_group) { _edit_group->remove (this); } - if ((_edit_group = eg)) { + if ((_edit_group = eg) != 0) { _edit_group->add (this); } _session.set_dirty (); + edit_group_changed (src); /* EMIT SIGNAL */ +} +void +Route::drop_edit_group (void *src) +{ + _edit_group = 0; + _session.set_dirty (); edit_group_changed (src); /* EMIT SIGNAL */ } @@ -1850,16 +1779,27 @@ void Route::set_mix_group (RouteGroup *mg, void *src) { + if (mg == _mix_group) { + return; + } + if (_mix_group) { _mix_group->remove (this); } - if ((_mix_group = mg)) { + if ((_mix_group = mg) != 0) { _mix_group->add (this); } _session.set_dirty (); - + mix_group_changed (src); /* EMIT SIGNAL */ +} + +void +Route::drop_mix_group (void *src) +{ + _mix_group = 0; + _session.set_dirty (); mix_group_changed (src); /* EMIT SIGNAL */ } @@ -1872,18 +1812,17 @@ Route::set_comment (string cmt, void *src) } bool -Route::feeds (Route *o) +Route::feeds (boost::shared_ptr other) { uint32_t i, j; - IO& other = *o; IO& self = *this; uint32_t no = self.n_outputs(); - uint32_t ni = other.n_inputs (); + uint32_t ni = other->n_inputs (); for (i = 0; i < no; ++i) { for (j = 0; j < ni; ++j) { - if (self.output(i)->connected_to (other.input(j)->name())) { + if (self.output(i)->connected_to (other->input(j)->name())) { return true; } } @@ -1897,7 +1836,7 @@ Route::feeds (Route *o) for (i = 0; i < no; ++i) { for (j = 0; j < ni; ++j) { - if ((*r)->output(i)->connected_to (other.input (j)->name())) { + if ((*r)->output(i)->connected_to (other->input (j)->name())) { return true; } } @@ -1912,7 +1851,7 @@ Route::feeds (Route *o) for (i = 0; i < no; ++i) { for (j = 0; j < ni; ++j) { - if (_control_outs->output(i)->connected_to (other.input (j)->name())) { + if (_control_outs->output(i)->connected_to (other->input (j)->name())) { return true; } } @@ -1979,16 +1918,12 @@ Route::set_active (bool yn) } void -Route::transport_stopped (bool abort_ignored, bool did_locate, bool can_flush_redirects) +Route::handle_transport_stopped (bool abort_ignored, bool did_locate, bool can_flush_redirects) { - jack_nframes_t now = _session.transport_frame(); + nframes_t now = _session.transport_frame(); { - RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__); - - if (!did_locate) { - automation_snapshot (now); - } + Glib::RWLock::ReaderLock lm (redirect_lock); for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { @@ -2006,19 +1941,6 @@ Route::transport_stopped (bool abort_ignored, bool did_locate, bool can_flush_re _roll_delay = _initial_delay; } -UndoAction -Route::get_memento() const -{ - void (Route::*pmf)(state_id_t) = &Route::set_state; - return sigc::bind (mem_fun (*(const_cast(this)), pmf), _current_state_id); -} - -void -Route::set_state (state_id_t id) -{ - return; -} - void Route::input_change_handler (IOChange change, void *ignored) { @@ -2050,7 +1972,7 @@ Route::pans_required () const } int -Route::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, +Route::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, bool session_state_changing, bool can_record, bool rec_monitors_input) { if (n_outputs() == 0) { @@ -2073,8 +1995,8 @@ Route::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes return 0; } -jack_nframes_t -Route::check_initial_delay (jack_nframes_t nframes, jack_nframes_t& offset, jack_nframes_t& transport_frame) +nframes_t +Route::check_initial_delay (nframes_t nframes, nframes_t& offset, nframes_t& transport_frame) { if (_roll_delay > nframes) { @@ -2099,24 +2021,15 @@ Route::check_initial_delay (jack_nframes_t nframes, jack_nframes_t& offset, jack } int -Route::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick, +Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, int declick, bool can_record, bool rec_monitors_input) { - { - TentativeRWLockMonitor lm(redirect_lock, false, __LINE__, __FILE__); - if (lm.locked()) { - // automation snapshot can also be called from the non-rt context - // and it uses the redirect list, so we take the lock out here - automation_snapshot (_session.transport_frame()); - } - } - if ((n_outputs() == 0 && _redirects.empty()) || n_inputs() == 0 || !_active) { silence (nframes, offset); return 0; } - jack_nframes_t unused = 0; + nframes_t unused = 0; if ((nframes = check_initial_delay (nframes, offset, unused)) == 0) { return 0; @@ -2127,11 +2040,11 @@ Route::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t apply_gain_automation = false; { - TentativeLockMonitor am (automation_lock, __LINE__, __FILE__); + Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK); if (am.locked() && _session.transport_rolling()) { - jack_nframes_t start_frame = end_frame - nframes; + nframes_t start_frame = end_frame - nframes; if (gain_automation_playback()) { apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes); @@ -2145,7 +2058,7 @@ Route::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t } int -Route::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, +Route::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, bool can_record, bool rec_monitors_input) { silence (nframes, offset); @@ -2156,17 +2069,17 @@ void Route::toggle_monitor_input () { for (vector::iterator i = _inputs.begin(); i != _inputs.end(); ++i) { - (*i)->request_monitor_input(!(*i)->monitoring_input()); + (*i)->ensure_monitor_input(!(*i)->monitoring_input()); } } bool Route::has_external_redirects () const { - const PortInsert* pi; + boost::shared_ptr pi; for (RedirectList::const_iterator i = _redirects.begin(); i != _redirects.end(); ++i) { - if ((pi = dynamic_cast(*i)) != 0) { + if ((pi = boost::dynamic_pointer_cast(*i)) != 0) { uint32_t no = pi->n_outputs(); @@ -2187,67 +2100,6 @@ Route::has_external_redirects () const return false; } -void -Route::reset_midi_control (MIDI::Port* port, bool on) -{ - MIDI::channel_t chn; - MIDI::eventType ev; - MIDI::byte extra; - - for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { - (*i)->reset_midi_control (port, on); - } - - IO::reset_midi_control (port, on); - - _midi_solo_control.get_control_info (chn, ev, extra); - if (!on) { - chn = -1; - } - _midi_solo_control.midi_rebind (port, chn); - - _midi_mute_control.get_control_info (chn, ev, extra); - if (!on) { - chn = -1; - } - _midi_mute_control.midi_rebind (port, chn); -} - -void -Route::send_all_midi_feedback () -{ - if (_session.get_midi_feedback()) { - - { - RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__); - for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { - (*i)->send_all_midi_feedback (); - } - } - - IO::send_all_midi_feedback(); - - _midi_solo_control.send_feedback (_soloed); - _midi_mute_control.send_feedback (_muted); - } -} - -MIDI::byte* -Route::write_midi_feedback (MIDI::byte* buf, int32_t& bufsize) -{ - buf = _midi_solo_control.write_feedback (buf, bufsize, _soloed); - buf = _midi_mute_control.write_feedback (buf, bufsize, _muted); - - { - RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__); - for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { - buf = (*i)->write_midi_feedback (buf, bufsize); - } - } - - return IO::write_midi_feedback (buf, bufsize); -} - void Route::flush_redirects () { @@ -2255,7 +2107,7 @@ Route::flush_redirects () this is called from the RT audio thread. */ - RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__); + Glib::RWLock::ReaderLock lm (redirect_lock); for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { (*i)->deactivate (); @@ -2273,7 +2125,7 @@ Route::set_meter_point (MeterPoint p, void *src) } } -jack_nframes_t +nframes_t Route::update_total_latency () { _own_latency = 0; @@ -2299,7 +2151,7 @@ Route::update_total_latency () } void -Route::set_latency_delay (jack_nframes_t longest_session_latency) +Route::set_latency_delay (nframes_t longest_session_latency) { _initial_delay = longest_session_latency - _own_latency; @@ -2308,120 +2160,50 @@ Route::set_latency_delay (jack_nframes_t longest_session_latency) } } -void -Route::automation_snapshot (jack_nframes_t now) -{ - IO::automation_snapshot (now); - - for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { - (*i)->automation_snapshot (now); - } -} - -Route::MIDIToggleControl::MIDIToggleControl (Route& s, ToggleType tp, MIDI::Port* port) - : MIDI::Controllable (port, true), route (s), type(tp), setting(false) +Route::ToggleControllable::ToggleControllable (std::string name, Route& s, ToggleType tp) + : Controllable (name), route (s), type(tp) { - last_written = false; /* XXX need a good out-of-bound-value */ + } void -Route::MIDIToggleControl::set_value (float val) +Route::ToggleControllable::set_value (float val) { - MIDI::eventType et; - MIDI::channel_t chn; - MIDI::byte additional; - - get_control_info (chn, et, additional); - - setting = true; - -#ifdef HOLD_TOGGLE_VALUES - if (et == MIDI::off || et == MIDI::on) { - - /* literal toggle */ - - switch (type) { - case MuteControl: - route.set_mute (!route.muted(), this); - break; - case SoloControl: - route.set_solo (!route.soloed(), this); - break; - default: - break; - } - - } else { -#endif - - /* map full control range to a boolean */ - - bool bval = ((val >= 0.5f) ? true: false); - - switch (type) { - case MuteControl: - route.set_mute (bval, this); - break; - case SoloControl: - route.set_solo (bval, this); - break; - default: - break; - } - -#ifdef HOLD_TOGGLE_VALUES + bool bval = ((val >= 0.5f) ? true: false); + + switch (type) { + case MuteControl: + route.set_mute (bval, this); + break; + case SoloControl: + route.set_solo (bval, this); + break; + default: + break; } -#endif - - setting = false; } -void -Route::MIDIToggleControl::send_feedback (bool value) +float +Route::ToggleControllable::get_value (void) const { - - if (!setting && get_midi_feedback()) { - MIDI::byte val = (MIDI::byte) (value ? 127: 0); - MIDI::channel_t ch = 0; - MIDI::eventType ev = MIDI::none; - MIDI::byte additional = 0; - MIDI::EventTwoBytes data; - - if (get_control_info (ch, ev, additional)) { - data.controller_number = additional; - data.value = val; - last_written = value; - - route._session.send_midi_message (get_port(), ev, ch, data); - } - } + float val = 0.0f; -} - -MIDI::byte* -Route::MIDIToggleControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force) -{ - if (get_midi_feedback() && bufsize > 2) { - MIDI::channel_t ch = 0; - MIDI::eventType ev = MIDI::none; - MIDI::byte additional = 0; - - if (get_control_info (ch, ev, additional)) { - if (val != last_written || force) { - *buf++ = (0xF0 & ev) | (0xF & ch); - *buf++ = additional; /* controller number */ - *buf++ = (MIDI::byte) (val ? 127 : 0); - bufsize -= 3; - last_written = val; - } - } + switch (type) { + case MuteControl: + val = route.muted() ? 1.0f : 0.0f; + break; + case SoloControl: + val = route.soloed() ? 1.0f : 0.0f; + break; + default: + break; } - return buf; + return val; } void -Route::set_block_size (jack_nframes_t nframes) +Route::set_block_size (nframes_t nframes) { for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { (*i)->set_block_size (nframes); @@ -2456,8 +2238,8 @@ Route::protect_automation () } for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { - PluginInsert* pi; - if ((pi = dynamic_cast (*i)) != 0) { + boost::shared_ptr pi; + if ((pi = boost::dynamic_pointer_cast (*i)) != 0) { pi->protect_automation (); } }