#include "ardour/session.h"
#include "ardour/mute_control.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
using namespace ARDOUR;
using namespace std;
set_flags (Controllable::Flag (flags() | Controllable::RealTime));
}
+void
+MuteControl::post_add_master (boost::shared_ptr<AutomationControl> m)
+{
+ if (m->get_value()) {
+
+ /* boolean masters records are not updated until AFTER
+ * ::post_add_master() is called, so we can use them to check
+ * on whether any master was already enabled before the new
+ * one was added.
+ */
+
+ if (!muted_by_self() && !get_boolean_masters()) {
+ _muteable.mute_master()->set_muted_by_masters (true);
+ Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
+ }
+ }
+}
+
+void
+MuteControl::pre_remove_master (boost::shared_ptr<AutomationControl> m)
+{
+ if (!m) {
+ /* null control ptr means we're removing all masters */
+ _muteable.mute_master()->set_muted_by_masters (false);
+ /* Changed will be emitted in SlavableAutomationControl::clear_masters() */
+ return;
+ }
+
+ if (m->get_value() && get_boolean_masters() == 1) {
+ _muteable.mute_master()->set_muted_by_masters (false);
+ if (!muted_by_self()) {
+ Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
+ }
+ }
+}
+
void
MuteControl::actually_set_value (double val, Controllable::GroupControlDisposition gcd)
{
_muteable.act_on_mute ();
}
- AutomationControl::actually_set_value (val, gcd);
+ SlavableAutomationControl::actually_set_value (val, gcd);
}
-void
-MuteControl::master_changed (bool self_change, Controllable::GroupControlDisposition gcd)
+bool
+MuteControl::handle_master_change (boost::shared_ptr<AutomationControl> m)
{
- 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
- */
+ bool send_signal = false;
+ boost::shared_ptr<MuteControl> mc = boost::dynamic_pointer_cast<MuteControl> (m);
+ if (!mc) {
+ return false;
+ }
- 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";
+ if (m->get_value()) {
+ /* this master is now enabled */
+ if (get_boolean_masters() == 0) {
+ _muteable.mute_master()->set_muted_by_masters (true);
+ if (!muted_by_self()) {
+ send_signal = true;
}
- } 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";
+ /* this master is disabled and there was only 1 enabled before */
+ if (get_boolean_masters() == 1) {
+ _muteable.mute_master()->set_muted_by_masters (false);
+ if (!muted_by_self()) {
+ send_signal = true;
}
- } else {
- cerr << "muted by self, not relevant\n";
}
}
+ return send_signal;
}
double
MuteControl::get_value () const
{
if (slaved ()) {
- Glib::Threads::RWLock::ReaderLock lm (master_lock);
- return get_masters_value_locked ();
+ return muted_by_self() || muted_by_masters ();
}
if (_list && boost::dynamic_pointer_cast<AutomationList>(_list)->automation_playback()) {
return AutomationControl::get_value();
}
- return muted() ? 1.0 : 0.0;
+ return muted();
}
void
bool
MuteControl::muted () const
{
- return _muteable.mute_master()->muted_by_self() || _muteable.mute_master()->muted_by_others();
+ /* have to get (self-muted) value from somewhere. could be our own
+ Control, or the Muteable that we sort-of proxy for. Since this
+ method is called by ::get_value(), use the latter to avoid recursion.
+ */
+ return _muteable.mute_master()->muted_by_self() || muted_by_masters ();
}
bool
}
bool
-MuteControl::muted_by_others () const
+MuteControl::muted_by_masters () const
+{
+ return _muteable.mute_master()->muted_by_masters ();
+}
+
+bool
+MuteControl::muted_by_others_soloing () const
{
- return _muteable.mute_master()->muted_by_others ();
+ return _muteable.muted_by_others_soloing ();
+}
+
+void
+MuteControl::automation_run (framepos_t start, pframes_t len)
+{
+ boolean_automation_run (start, len);
+
+ bool valid = false;
+ bool mute = false;
+
+ if (list() && automation_playback()) {
+ mute = list()->rt_safe_eval (start, valid) >= 0.5;
+ }
+
+ if (!valid) {
+ return;
+ }
+
+ if (muted_by_masters ()) {
+ /* already muted, no need to check further,
+ * except we need to up update implicit/explict mute
+ */
+ if (muted_by_self () != mute) {
+ set_value_unchecked (mute ? 1. : 0.);
+ Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
+ }
+ return;
+ }
+
+ if (mute && !muted()) {
+ set_value_unchecked (1.0); // mute
+ Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
+ } else if (!mute && muted()) {
+ set_value_unchecked (0.0); // unmute
+ Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
+ }
}