a variety of changes that get closer to correctly functioning behaviour for VCA solo+mute (BUT ARE NOT DONE YET)

This commit is contained in:
Paul Davis 2016-04-15 00:38:03 -04:00
parent 7d493b091a
commit 6de4953be8
13 changed files with 162 additions and 84 deletions

View File

@ -415,7 +415,7 @@ RouteUI::mute_press (GdkEventButton* ev)
}
DisplaySuspender ds;
_session->set_controls (route_list_to_control_list (copy, &Route::mute_control), _route->muted() ? 0.0 : 1.0, Controllable::UseGroup);
_session->set_controls (route_list_to_control_list (copy, &Route::mute_control), _route->muted_by_self() ? 0.0 : 1.0, Controllable::UseGroup);
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
@ -444,7 +444,7 @@ RouteUI::mute_press (GdkEventButton* ev)
}
DisplaySuspender ds;
_session->set_controls (route_list_to_control_list (rl, &Route::mute_control), _route->muted() ? 0.0 : 1.0, Controllable::InverseGroup);
_session->set_controls (route_list_to_control_list (rl, &Route::mute_control), _route->muted_by_self() ? 0.0 : 1.0, Controllable::InverseGroup);
}
} else {
@ -458,7 +458,7 @@ RouteUI::mute_press (GdkEventButton* ev)
_mute_release->routes = rl;
}
_session->set_control (_route->mute_control(), _route->muted() ? 0.0 : 1.0, Controllable::UseGroup);
_session->set_control (_route->mute_control(), _route->muted_by_self() ? 0.0 : 1.0, Controllable::UseGroup);
}
}
@ -1225,10 +1225,12 @@ RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
if (r->muted ()) {
std::cerr << r->name() << " self " << r->mute_control()->muted_by_self() << " others " << r->muted_by_others() << " soloing " << r->muted_by_others_soloing() << std::endl;
if (r->mute_control()->muted_by_self ()) {
/* full mute */
return Gtkmm2ext::ExplicitActive;
} else if (r->muted_by_others_soloing () || r->mute_control()->get_masters_value()) {
} else if (r->muted_by_others_soloing () || r->muted_by_others()) {
/* this will reflect both solo mutes AND master mutes */
return Gtkmm2ext::ImplicitActive;
} else {
@ -1238,15 +1240,11 @@ RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
} else {
if (r->muted()) {
if (r->mute_control()->muted_by_self()) {
/* full mute */
return Gtkmm2ext::ExplicitActive;
} else if (r->muted_by_others()) {
/* note the direct use of MuteMaster API here. We are
not interested in showing
others-soloed-so-this-muted status in this
conditional branch.
*/
/* this shows only master mutes, not mute-by-others-soloing */
return Gtkmm2ext::ImplicitActive;
} else {
/* no mute at all */

View File

@ -131,6 +131,8 @@ VCAMasterStrip::VCAMasterStrip (Session* s, boost::shared_ptr<VCA> v)
_vca->solo_control()->Changed.connect (vca_connections, invalidator (*this), boost::bind (&VCAMasterStrip::solo_changed, this), gui_context());
_vca->mute_control()->Changed.connect (vca_connections, invalidator (*this), boost::bind (&VCAMasterStrip::mute_changed, this), gui_context());
/* only need to connect to one of these to update VCA status */
_vca->gain_control()->MasterStatusChange.connect (vca_connections,
invalidator (*this),
boost::bind (&VCAMasterStrip::update_vca_display, this),
@ -198,14 +200,20 @@ VCAMasterStrip::set_selected (bool yn)
bool
VCAMasterStrip::solo_release (GdkEventButton*)
{
_vca->solo_control()->set_value (_vca->solo_control()->get_value() ? 0.0 : 1.0, Controllable::NoGroup);
/* We use NoGroup because VCA controls are never part of a group. This
is redundant, but clear.
*/
_vca->solo_control()->set_value (_vca->solo_control()->self_soloed() ? 0.0 : 1.0, Controllable::NoGroup);
return true;
}
bool
VCAMasterStrip::mute_release (GdkEventButton*)
{
_vca->mute_control()->set_value (_vca->mute_control()->get_value() ? 0.0 : 1.0, Controllable::NoGroup);
/* We use NoGroup because VCA controls are never part of a group. This
is redundant, but clear.
*/
_vca->mute_control()->set_value (_vca->mute_control()->muted_by_self() ? 0.0 : 1.0, Controllable::NoGroup);
return true;
}
@ -229,8 +237,11 @@ VCAMasterStrip::set_solo_text ()
void
VCAMasterStrip::mute_changed ()
{
if (_vca->mute_control()->muted()) {
std::cerr << "Mute changed for " << _vca->number() << std::endl;
if (_vca->mute_control()->muted_by_self()) {
mute_button.set_active_state (ExplicitActive);
} else if (_vca->mute_control()->muted_by_others()) {
mute_button.set_active_state (ImplicitActive);
} else {
mute_button.set_active_state (Gtkmm2ext::Off);
}
@ -239,7 +250,7 @@ VCAMasterStrip::mute_changed ()
void
VCAMasterStrip::solo_changed ()
{
if (_vca->solo_control()->soloed()) {
if (_vca->solo_control()->soloed() || _vca->solo_control()->get_masters_value()) {
solo_button.set_active_state (ExplicitActive);
} else {
solo_button.set_active_state (Gtkmm2ext::Off);
@ -257,10 +268,14 @@ VCAMasterStrip::vca_menu_toggle (CheckMenuItem* menuitem, uint32_t n)
vca_unassign ();
} else {
_vca->gain_control()->remove_master (vca->gain_control());
_vca->solo_control()->remove_master (vca->solo_control());
_vca->mute_control()->remove_master (vca->mute_control());
}
} else {
if (vca) {
_vca->gain_control()->add_master (vca->gain_control());
_vca->mute_control()->add_master (vca->mute_control());
_vca->solo_control()->add_master (vca->solo_control());
}
}
}
@ -269,6 +284,8 @@ void
VCAMasterStrip::vca_unassign ()
{
_vca->gain_control()->clear_masters ();
_vca->solo_control()->clear_masters ();
_vca->mute_control()->clear_masters ();
}
bool

View File

@ -152,8 +152,6 @@ class SlavableAutomationControl : public AutomationControl
boost::shared_ptr<ARDOUR::AutomationList> l=boost::shared_ptr<ARDOUR::AutomationList>(),
const std::string& name="");
~SlavableAutomationControl ();
double get_value () const;
void add_master (boost::shared_ptr<AutomationControl>);
@ -200,7 +198,7 @@ class SlavableAutomationControl : public AutomationControl
virtual void recompute_masters_ratios (double val) { /* do nothing by default */}
virtual double get_masters_value_locked () const;
double get_value_locked() const;
void actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
};

View File

@ -59,8 +59,6 @@ class LIBARDOUR_API GainControl : public SlavableAutomationControl {
void vcas_loaded();
void recompute_masters_ratios (double val);
void actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
};
} /* namespace */

View File

@ -53,6 +53,7 @@ class LIBARDOUR_API MuteControl : public SlavableAutomationControl
*/
bool muted () const;
bool muted_by_self () const;
bool muted_by_others_soloing () const;
bool muted_by_others () const;
@ -61,6 +62,7 @@ class LIBARDOUR_API MuteControl : public SlavableAutomationControl
MuteMaster::MutePoint mute_points () const;
protected:
void master_changed (bool, PBD::Controllable::GroupControlDisposition);
void actually_set_value (double, PBD::Controllable::GroupControlDisposition group_override);
private:

View File

@ -70,7 +70,7 @@ class LIBARDOUR_API MuteMaster : public SessionHandleRef, public PBD::Stateful
void set_solo_ignore (bool yn) { _solo_ignore = yn; }
void mod_muted_by_others (int32_t delta);
bool muted_by_others () const { return _muted_by_others; }
int32_t muted_by_others () const { return _muted_by_others; }
PBD::Signal0<void> MutePointChanged;

View File

@ -460,8 +460,9 @@ public:
bool can_be_muted_by_others () const { return !is_master(); }
bool muted () const { return _mute_control->muted(); }
bool muted_by_others () const { return _mute_control->muted_by_others(); }
bool muted_by_self () const { return _mute_control->muted_by_self(); }
bool muted_by_others_soloing () const;
bool muted_by_others () const;
boost::shared_ptr<SoloIsolateControl> solo_isolate_control() const {
return _solo_isolate_control;

View File

@ -43,28 +43,6 @@ GainControl::GainControl (Session& session, const Evoral::Parameter &param, boos
range_db = accurate_coefficient_to_dB (_desc.upper) - lower_db;
}
void
GainControl::actually_set_value (double val, Controllable::GroupControlDisposition group_override)
{
val = std::max (std::min (val, (double)_desc.upper), (double)_desc.lower);
{
Glib::Threads::RWLock::WriterLock lm (master_lock);
if (!_masters.empty()) {
recompute_masters_ratios (val);
}
}
/* this sets the Evoral::Control::_user_value for us, which will
be retrieved by AutomationControl::get_value ()
*/
AutomationControl::actually_set_value (val, group_override);
_session.set_dirty ();
}
double
GainControl::internal_to_interface (double v) const
{

View File

@ -42,7 +42,7 @@ MuteControl::MuteControl (Session& session, std::string const & name, Muteable&
void
MuteControl::actually_set_value (double val, Controllable::GroupControlDisposition gcd)
{
if (muted() != bool (val)) {
if (muted_by_self() != bool (val)) {
_muteable.mute_master()->set_muted_by_self (val);
/* allow the Muteable to respond to the mute change
@ -54,12 +54,63 @@ MuteControl::actually_set_value (double val, Controllable::GroupControlDispositi
AutomationControl::actually_set_value (val, gcd);
}
void
MuteControl::master_changed (bool self_change, Controllable::GroupControlDisposition gcd)
{
double m = get_masters_value ();
const int32_t old_muted_by_others = _muteable.mute_master()->muted_by_others ();
std::cerr << "master " << (self_change ? " self " : " not-self") << " changed to " << m << " old others = " << old_muted_by_others << std::endl;
_muteable.mute_master()->mod_muted_by_others (m ? 1 : -1);
if (m) {
/* master(s) are now muted. If we are self-muted, this
doesn't change our status. If we are not self-muted,
then it changes our status if either:
- the master had its own self-muted status changed OR
- the total number of masters that are muted used to be zero
*/
if (!muted_by_self()) {
if (self_change || old_muted_by_others == 0) {
/* note false as the first argument - our own
value was not changed
*/
Changed (false, gcd);
} else {
cerr << " no Change signal\n";
}
} else {
cerr << "muted by self, not relevant\n";
}
} else {
/* no master(s) are now muted. If we are self-muted, this
doesn't change our status. If we are not self-muted,
then it changes our status if either:
- the master had its own self-muted status changed OR
- the total number of masters that are muted used to be non-zero
*/
if (!muted_by_self()) {
if (self_change || old_muted_by_others != 0) {
Changed (false, gcd);
} else {
cerr << " No change signal\n";
}
} else {
cerr << "muted by self, not relevant\n";
}
}
}
double
MuteControl::get_value () const
{
if (slaved()) {
if (slaved ()) {
Glib::Threads::RWLock::ReaderLock lm (master_lock);
return get_masters_value_locked () ? 1.0 : 0.0;
return get_masters_value_locked ();
}
if (_list && boost::dynamic_pointer_cast<AutomationList>(_list)->automation_playback()) {
@ -89,6 +140,12 @@ MuteControl::mute_points () const
bool
MuteControl::muted () const
{
return _muteable.mute_master()->muted_by_self() || _muteable.mute_master()->muted_by_others();
}
bool
MuteControl::muted_by_self () const
{
return _muteable.mute_master()->muted_by_self();
}
@ -96,5 +153,5 @@ MuteControl::muted () const
bool
MuteControl::muted_by_others () const
{
return _muteable.mute_master()->muted_by_others () || get_masters_value();
return _muteable.mute_master()->muted_by_others ();
}

View File

@ -173,4 +173,5 @@ void
MuteMaster::mod_muted_by_others (int32_t delta)
{
_muted_by_others = max (0, _muted_by_others + delta);
std::cerr << this << " mod others by " << delta << " to get " << _muted_by_others << endl;
}

View File

@ -5481,29 +5481,15 @@ Route::vca_unassign (boost::shared_ptr<VCA> vca)
bool
Route::muted_by_others_soloing () const
{
// This method is only used by route_ui for display state.
// The DSP version is MuteMaster::muted_by_others_at()
if (!can_be_muted_by_others ()) {
return false;
}
/* XXX something needed here re: mute-overrides-solo */
return _session.soloing() && !_solo_control->soloed() && !_solo_isolate_control->solo_isolated();
}
bool
Route::muted_by_others () const
{
// This method is only used by route_ui for display state.
// The DSP version is MuteMaster::muted_by_others_at()
if (!can_be_muted_by_others()) {
return false;
}
return _mute_master->muted_by_others();
}
void
Route::clear_all_solo_state ()
{

View File

@ -19,6 +19,8 @@
#ifndef __libardour_slavable_automation_control_h__
#define __libardour_slavable_automation_control_h__
#include "pbd/enumwriter.h"
#include "ardour/automation_control.h"
#include "ardour/session.h"
@ -35,29 +37,26 @@ SlavableAutomationControl::SlavableAutomationControl(ARDOUR::Session& s,
{
}
SlavableAutomationControl::~SlavableAutomationControl ()
{
}
double
SlavableAutomationControl::get_masters_value_locked () const
{
gain_t v = _desc.normal;
double v = _desc.normal;
for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
if (_desc.toggled) {
/* if any master is enabled, the slaves are too */
if (_desc.toggled) {
for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
if (mr->second.master()->get_value()) {
return _desc.upper;
}
} else {
/* get current master value, scale by our current ratio with that master */
v *= mr->second.master()->get_value () * mr->second.ratio();
}
return _desc.lower;
}
return min (_desc.upper, v);
for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
/* get current master value, scale by our current ratio with that master */
v *= mr->second.master()->get_value () * mr->second.ratio();
}
return min ((double) _desc.upper, v);
}
double
@ -69,6 +68,16 @@ SlavableAutomationControl::get_value_locked() const
return Control::get_double (false, _session.transport_frame());
}
if (_desc.toggled) {
/* for boolean/toggle controls, if this slave OR any master is
* enabled, this slave is enabled. So check our own value
* first, because if we are enabled, we can return immediately.
*/
if (Control::get_double (false, _session.transport_frame())) {
return _desc.upper;
}
}
return get_masters_value_locked ();
}
@ -86,6 +95,27 @@ SlavableAutomationControl::get_value() const
}
}
void
SlavableAutomationControl::actually_set_value (double val, Controllable::GroupControlDisposition group_override)
{
val = std::max (std::min (val, (double)_desc.upper), (double)_desc.lower);
{
Glib::Threads::RWLock::WriterLock lm (master_lock);
if (!_masters.empty()) {
recompute_masters_ratios (val);
}
}
/* this sets the Evoral::Control::_user_value for us, which will
be retrieved by AutomationControl::get_value ()
*/
AutomationControl::actually_set_value (val, group_override);
_session.set_dirty ();
}
void
SlavableAutomationControl::add_master (boost::shared_ptr<AutomationControl> m)
{
@ -103,7 +133,9 @@ SlavableAutomationControl::add_master (boost::shared_ptr<AutomationControl> m)
if (res.second) {
recompute_masters_ratios (current_value);
if (_desc.toggled) {
recompute_masters_ratios (current_value);
}
/* note that we bind @param m as a weak_ptr<AutomationControl>, thus
avoiding holding a reference to the control in the binding
@ -145,13 +177,17 @@ SlavableAutomationControl::add_master (boost::shared_ptr<AutomationControl> m)
void
SlavableAutomationControl::master_changed (bool /*from_self*/, GroupControlDisposition gcd)
{
cerr << this << enum_2_string ((AutomationType)_parameter.type()) << " master changed, relay changed along\n";
/* our value has (likely) changed, but not because we were
* modified. Just the master.
*/
Changed (false, gcd); /* EMIT SIGNAL */
/* propagate master state into our own control so that if we stop
* being slaved, our value doesn't change, and propagate to any
* group this control is part of.
*/
cerr << this << ' ' << enum_2_string ((AutomationType) _parameter.type()) << " pass along " << get_masters_value() << " from master to group\n";
actually_set_value (get_masters_value(), Controllable::UseGroup);
}
void
@ -168,6 +204,7 @@ SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m
{
double current_value;
double new_value;
bool masters_left;
Masters::size_type erased = 0;
{
@ -177,6 +214,7 @@ SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m
if (erased) {
recompute_masters_ratios (current_value);
}
masters_left = _masters.size ();
new_value = get_value_locked ();
}
@ -185,7 +223,12 @@ SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m
}
if (new_value != current_value) {
Changed (false, Controllable::NoGroup);
if (masters_left == 0) {
/* no masters left, make sure we keep the same value
that we had before.
*/
actually_set_value (current_value, Controllable::UseGroup);
}
}
}

View File

@ -155,8 +155,7 @@ SoloControl::actually_set_value (double val, PBD::Controllable::GroupControlDisp
be retrieved by AutomationControl::get_value (), and emits Changed
*/
AutomationControl::actually_set_value (val, group_override);
_session.set_dirty ();
SlavableAutomationControl::actually_set_value (val, group_override);
}
double