diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index dda8fa0da5..7e35430b7a 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -3884,264 +3884,6 @@ Route::set_latency_compensation (framecnt_t longest_session_latency) } } -void -Route::set_control (AutomationType type, double val, PBD::Controllable::GroupControlDisposition group_override) -{ - boost::shared_ptr rl; - - switch (type) { - case GainAutomation: - /* route must mediate group control */ - set_gain (val, group_override); - return; - break; - - case TrimAutomation: - /* route must mediate group control */ - set_trim (val, group_override); - return; - break; - - case RecEnableAutomation: - /* session must mediate group control */ - rl.reset (new RouteList); - rl->push_back (shared_from_this()); - _session.set_record_enabled (rl, val >= 0.5 ? true : false, Session::rt_cleanup, group_override); - return; - break; - - case SoloAutomation: - /* session must mediate group control */ - rl.reset (new RouteList); - rl->push_back (shared_from_this()); - if (Config->get_solo_control_is_listen_control()) { - _session.set_listen (rl, val >= 0.5 ? true : false, Session::rt_cleanup, group_override); - } else { - _session.set_solo (rl, val >= 0.5 ? true : false); - } - - return; - break; - - case MuteAutomation: - /* session must mediate group control */ - rl.reset (new RouteList); - rl->push_back (shared_from_this()); - _session.set_mute (rl, !muted(), Session::rt_cleanup, group_override); - return; - break; - - default: - /* Not a route automation control */ - fatal << string_compose (_("programming error: %1%2\n"), X_("illegal type of route automation control passed to Route::set_control(): "), enum_2_string(type)) << endmsg; - /*NOTREACHED*/ - return; - } -} - - -Route::RouteAutomationControl::RouteAutomationControl (const std::string& name, - AutomationType atype, - boost::shared_ptr alist, - boost::shared_ptr r) - : AutomationControl (r->session(), Evoral::Parameter (atype), - ParameterDescriptor (Evoral::Parameter (atype)), - alist, name) - , _route (r) -{ -} - -Route::GainControllable::GainControllable (Session& s, AutomationType atype, boost::shared_ptr r) - : GainControl (s, Evoral::Parameter(atype)) - , _route (r) -{ - -} - -Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr r) - : RouteAutomationControl (name, SoloAutomation, boost::shared_ptr(), r) -{ - boost::shared_ptr gl(new AutomationList(Evoral::Parameter(SoloAutomation))); - gl->set_interpolation(Evoral::ControlList::Discrete); - set_list (gl); -} - -void -Route::SoloControllable::set_value (double val, PBD::Controllable::GroupControlDisposition group_override) -{ - if (writable()) { - _set_value (val, group_override); - } -} - -void -Route::SoloControllable::_set_value (double val, PBD::Controllable::GroupControlDisposition group_override) -{ - const bool bval = ((val >= 0.5) ? true : false); - - boost::shared_ptr rl (new RouteList); - - boost::shared_ptr r = _route.lock (); - if (!r) { - return; - } - - rl->push_back (r); - - if (Config->get_solo_control_is_listen_control()) { - _session.set_listen (rl, bval, Session::rt_cleanup, group_override); - } else { - _session.set_solo (rl, bval, Session::rt_cleanup, group_override); - } -} - -void -Route::SoloControllable::set_value_unchecked (double val) -{ - /* Used only by automation playback */ - - _set_value (val, Controllable::NoGroup); -} - -double -Route::SoloControllable::get_value () const -{ - boost::shared_ptr r = _route.lock (); - if (!r) { - return 0; - } - - if (Config->get_solo_control_is_listen_control()) { - return r->listening_via_monitor() ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO; - } else { - return r->self_soloed() ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO; - } -} - -Route::MuteControllable::MuteControllable (std::string name, boost::shared_ptr r) - : RouteAutomationControl (name, MuteAutomation, boost::shared_ptr(), r) - , _route (r) -{ - boost::shared_ptr gl(new AutomationList(Evoral::Parameter(MuteAutomation))); - gl->set_interpolation(Evoral::ControlList::Discrete); - set_list (gl); -} - -void -Route::MuteControllable::set_superficial_value(bool muted) -{ - /* Note we can not use AutomationControl::set_value here since it will emit - Changed(), but the value will not be correct to the observer. */ - - const bool to_list = _list && ((AutomationList*)_list.get ())->automation_write (); - const double where = _session.audible_frame (); - if (to_list) { - /* Note that we really need this: - * if (as == Touch && _list->in_new_write_pass ()) { - * alist->start_write_pass (_session.audible_frame ()); - * } - * here in the case of the user calling from a GUI or whatever. - * Without the ability to distinguish between user and - * automation-initiated changes, we lose the "touch mute" - * behaviour we have in AutomationController::toggled (). - */ - _list->set_in_write_pass (true, false, where); - } - - Control::set_double (muted, where, to_list); -} - -void -Route::MuteControllable::set_value (double val, PBD::Controllable::GroupControlDisposition group_override) -{ - if (writable()) { - _set_value (val, group_override); - } -} - -void -Route::MuteControllable::set_value_unchecked (double val) -{ - /* used only automation playback */ - _set_value (val, Controllable::NoGroup); -} - -void -Route::MuteControllable::_set_value (double val, Controllable::GroupControlDisposition group_override) -{ - const bool bval = ((val >= 0.5) ? true : false); - - boost::shared_ptr r = _route.lock (); - if (!r) { - return; - } - - if (_list && ((AutomationList*)_list.get())->automation_playback()) { - // Set superficial/automation value to drive controller (and possibly record) - set_superficial_value (bval); - // Playing back automation, set route mute directly - r->set_mute (bval, Controllable::NoGroup); - } else { - // Set from user, queue mute event - boost::shared_ptr rl (new RouteList); - rl->push_back (r); - _session.set_mute (rl, bval, Session::rt_cleanup, group_override); - } -} - -double -Route::MuteControllable::get_value () const -{ - if (_list && ((AutomationList*)_list.get())->automation_playback()) { - // Playing back automation, get the value from the list - return AutomationControl::get_value(); - } - - // Not playing back automation, get the actual route mute value - boost::shared_ptr r = _route.lock (); - return (r && r->muted()) ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO; -} - -Route::PhaseControllable::PhaseControllable (std::string name, boost::shared_ptr r) - : RouteAutomationControl (name, PhaseAutomation, boost::shared_ptr(), r) -{ - boost::shared_ptr gl(new AutomationList(Evoral::Parameter(PhaseAutomation))); - gl->set_interpolation(Evoral::ControlList::Discrete); - set_list (gl); -} - -void -Route::PhaseControllable::set_value (double v, PBD::Controllable::GroupControlDisposition /* group_override */) -{ - boost::shared_ptr r = _route.lock (); - if (r->phase_invert().size()) { - if (v == 0 || (v < 1 && v > 0.9) ) { - r->set_phase_invert (_current_phase, false); - } else { - r->set_phase_invert (_current_phase, true); - } - } -} - -double -Route::PhaseControllable::get_value () const -{ - boost::shared_ptr r = _route.lock (); - return (double) r->phase_invert (_current_phase); -} - -void -Route::PhaseControllable::set_channel (uint32_t c) -{ - _current_phase = c; -} - -uint32_t -Route::PhaseControllable::channel () const -{ - return _current_phase; -} - void Route::set_block_size (pframes_t nframes) { diff --git a/libs/ardour/route_controls.cc b/libs/ardour/route_controls.cc new file mode 100644 index 0000000000..71e44ef91c --- /dev/null +++ b/libs/ardour/route_controls.cc @@ -0,0 +1,291 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifdef WAF_BUILD +#include "libardour-config.h" +#endif + +#include "ardour/automation_control.h" +#include "ardour/route.h" +#include "ardour/session.h" + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; +using namespace PBD; + +void +Route::set_control (AutomationType type, double val, PBD::Controllable::GroupControlDisposition group_override) +{ + boost::shared_ptr rl; + + switch (type) { + case GainAutomation: + /* route must mediate group control */ + set_gain (val, group_override); + return; + break; + + case TrimAutomation: + /* route must mediate group control */ + set_trim (val, group_override); + return; + break; + + case RecEnableAutomation: + /* session must mediate group control */ + rl.reset (new RouteList); + rl->push_back (shared_from_this()); + _session.set_record_enabled (rl, val >= 0.5 ? true : false, Session::rt_cleanup, group_override); + return; + break; + + case SoloAutomation: + /* session must mediate group control */ + rl.reset (new RouteList); + rl->push_back (shared_from_this()); + if (Config->get_solo_control_is_listen_control()) { + _session.set_listen (rl, val >= 0.5 ? true : false, Session::rt_cleanup, group_override); + } else { + _session.set_solo (rl, val >= 0.5 ? true : false); + } + + return; + break; + + case MuteAutomation: + /* session must mediate group control */ + rl.reset (new RouteList); + rl->push_back (shared_from_this()); + _session.set_mute (rl, !muted(), Session::rt_cleanup, group_override); + return; + break; + + default: + /* Not a route automation control */ + fatal << string_compose (_("programming error: %1%2\n"), X_("illegal type of route automation control passed to Route::set_control(): "), enum_2_string(type)) << endmsg; + /*NOTREACHED*/ + return; + } +} + + +Route::RouteAutomationControl::RouteAutomationControl (const std::string& name, + AutomationType atype, + boost::shared_ptr alist, + boost::shared_ptr r) + : AutomationControl (r->session(), Evoral::Parameter (atype), + ParameterDescriptor (Evoral::Parameter (atype)), + alist, name) + , _route (r) +{ +} + +Route::GainControllable::GainControllable (Session& s, AutomationType atype, boost::shared_ptr r) + : GainControl (s, Evoral::Parameter(atype)) + , _route (r) +{ + +} + +Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr r) + : RouteAutomationControl (name, SoloAutomation, boost::shared_ptr(), r) +{ + boost::shared_ptr gl(new AutomationList(Evoral::Parameter(SoloAutomation))); + gl->set_interpolation(Evoral::ControlList::Discrete); + set_list (gl); +} + +void +Route::SoloControllable::set_value (double val, PBD::Controllable::GroupControlDisposition group_override) +{ + if (writable()) { + _set_value (val, group_override); + } +} + +void +Route::SoloControllable::_set_value (double val, PBD::Controllable::GroupControlDisposition group_override) +{ + const bool bval = ((val >= 0.5) ? true : false); + + boost::shared_ptr rl (new RouteList); + + boost::shared_ptr r = _route.lock (); + if (!r) { + return; + } + + rl->push_back (r); + + if (Config->get_solo_control_is_listen_control()) { + _session.set_listen (rl, bval, Session::rt_cleanup, group_override); + } else { + _session.set_solo (rl, bval, Session::rt_cleanup, group_override); + } +} + +void +Route::SoloControllable::set_value_unchecked (double val) +{ + /* Used only by automation playback */ + + _set_value (val, Controllable::NoGroup); +} + +double +Route::SoloControllable::get_value () const +{ + boost::shared_ptr r = _route.lock (); + if (!r) { + return 0; + } + + if (Config->get_solo_control_is_listen_control()) { + return r->listening_via_monitor() ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO; + } else { + return r->self_soloed() ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO; + } +} + +Route::MuteControllable::MuteControllable (std::string name, boost::shared_ptr r) + : RouteAutomationControl (name, MuteAutomation, boost::shared_ptr(), r) + , _route (r) +{ + boost::shared_ptr gl(new AutomationList(Evoral::Parameter(MuteAutomation))); + gl->set_interpolation(Evoral::ControlList::Discrete); + set_list (gl); +} + +void +Route::MuteControllable::set_superficial_value(bool muted) +{ + /* Note we can not use AutomationControl::set_value here since it will emit + Changed(), but the value will not be correct to the observer. */ + + const bool to_list = _list && ((AutomationList*)_list.get ())->automation_write (); + const double where = _session.audible_frame (); + if (to_list) { + /* Note that we really need this: + * if (as == Touch && _list->in_new_write_pass ()) { + * alist->start_write_pass (_session.audible_frame ()); + * } + * here in the case of the user calling from a GUI or whatever. + * Without the ability to distinguish between user and + * automation-initiated changes, we lose the "touch mute" + * behaviour we have in AutomationController::toggled (). + */ + _list->set_in_write_pass (true, false, where); + } + + Control::set_double (muted, where, to_list); +} + +void +Route::MuteControllable::set_value (double val, PBD::Controllable::GroupControlDisposition group_override) +{ + if (writable()) { + _set_value (val, group_override); + } +} + +void +Route::MuteControllable::set_value_unchecked (double val) +{ + /* used only automation playback */ + _set_value (val, Controllable::NoGroup); +} + +void +Route::MuteControllable::_set_value (double val, Controllable::GroupControlDisposition group_override) +{ + const bool bval = ((val >= 0.5) ? true : false); + + boost::shared_ptr r = _route.lock (); + if (!r) { + return; + } + + if (_list && ((AutomationList*)_list.get())->automation_playback()) { + // Set superficial/automation value to drive controller (and possibly record) + set_superficial_value (bval); + // Playing back automation, set route mute directly + r->set_mute (bval, Controllable::NoGroup); + } else { + // Set from user, queue mute event + boost::shared_ptr rl (new RouteList); + rl->push_back (r); + _session.set_mute (rl, bval, Session::rt_cleanup, group_override); + } +} + +double +Route::MuteControllable::get_value () const +{ + if (_list && ((AutomationList*)_list.get())->automation_playback()) { + // Playing back automation, get the value from the list + return AutomationControl::get_value(); + } + + // Not playing back automation, get the actual route mute value + boost::shared_ptr r = _route.lock (); + return (r && r->muted()) ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO; +} + +Route::PhaseControllable::PhaseControllable (std::string name, boost::shared_ptr r) + : RouteAutomationControl (name, PhaseAutomation, boost::shared_ptr(), r) +{ + boost::shared_ptr gl(new AutomationList(Evoral::Parameter(PhaseAutomation))); + gl->set_interpolation(Evoral::ControlList::Discrete); + set_list (gl); +} + +void +Route::PhaseControllable::set_value (double v, PBD::Controllable::GroupControlDisposition /* group_override */) +{ + boost::shared_ptr r = _route.lock (); + if (r->phase_invert().size()) { + if (v == 0 || (v < 1 && v > 0.9) ) { + r->set_phase_invert (_current_phase, false); + } else { + r->set_phase_invert (_current_phase, true); + } + } +} + +double +Route::PhaseControllable::get_value () const +{ + boost::shared_ptr r = _route.lock (); + return (double) r->phase_invert (_current_phase); +} + +void +Route::PhaseControllable::set_channel (uint32_t c) +{ + _current_phase = c; +} + +uint32_t +Route::PhaseControllable::channel () const +{ + return _current_phase; +} + diff --git a/libs/ardour/wscript b/libs/ardour/wscript index a3ab30e8db..22aeb21dfa 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -169,6 +169,7 @@ libardour_sources = [ 'return.cc', 'reverse.cc', 'route.cc', + 'route_controls.cc', 'route_graph.cc', 'route_group.cc', 'route_group_member.cc',