#include "ardour/session.h"
#include "ardour/solo_control.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
using namespace ARDOUR;
using namespace std;
, _self_solo (false)
, _soloed_by_others_upstream (0)
, _soloed_by_others_downstream (0)
+ , _transition_into_solo (false)
{
_list->set_interpolation (Evoral::ControlList::Discrete);
/* solo changes must be synchronized by the process cycle */
DEBUG_TRACE (DEBUG::Solo, string_compose ("%1: set SELF solo => %2\n", name(), yn));
_self_solo = yn;
set_mute_master_solo ();
+
+ _transition_into_solo = 0;
+
+ if (yn) {
+ if (get_masters_value() == 0) {
+ _transition_into_solo = 1;
+ }
+ } else {
+ if (get_masters_value() == 0) {
+ _transition_into_solo = -1;
+ }
+ }
}
void
SoloControl::set_mute_master_solo ()
{
- _muteable.mute_master()->set_soloed_by_self (self_soloed());
+ _muteable.mute_master()->set_soloed_by_self (self_soloed() || get_masters_value());
if (Config->get_solo_control_is_listen_control()) {
_muteable.mute_master()->set_soloed_by_others (false);
} else {
- _muteable.mute_master()->set_soloed_by_others (soloed_by_others_downstream() || soloed_by_others_upstream());
+ _muteable.mute_master()->set_soloed_by_others (soloed_by_others_downstream() || soloed_by_others_upstream() || get_masters_value());
}
}
DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 SbD delta %2 = %3\n", name(), delta, _soloed_by_others_downstream));
set_mute_master_solo ();
+ _transition_into_solo = 0;
Changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
}
}
set_mute_master_solo ();
+ _transition_into_solo = 0;
Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
}
SoloControl::get_value () const
{
if (slaved()) {
- Glib::Threads::RWLock::ReaderLock lm (master_lock);
- return get_masters_value_locked () ? 1.0 : 0.0;
+ return self_soloed() || get_masters_value ();
}
if (_list && boost::dynamic_pointer_cast<AutomationList>(_list)->automation_playback()) {
return AutomationControl::get_value();
}
- return self_soloed() ? 1.0 : 0.0;
+ return soloed();
}
void
_soloed_by_others_downstream = 0;
set_self_solo (false);
-
+ _transition_into_solo = 0; /* Session does not need to propagate */
Changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
}
return node;
}
+
+void
+SoloControl::master_changed (bool /*from self*/, GroupControlDisposition, boost::shared_ptr<AutomationControl> m)
+{
+ bool send_signal = false;
+
+ _transition_into_solo = 0;
+
+ /* Notice that we call get_boolean_masters() BEFORE we call
+ * update_boolean_masters_records(), in order to know what
+ * our master state was BEFORE it gets changed.
+ */
+
+
+ if (m->get_value()) {
+ /* this master is now enabled */
+ if (!self_soloed() && get_boolean_masters() == 0) {
+ /* not self-soloed, wasn't soloed by masters before */
+ send_signal = true;
+ _transition_into_solo = 1;
+ }
+ } else {
+ if (!self_soloed() && get_boolean_masters() == 1) {
+ /* not self-soloed, soloed by just 1 master before */
+ _transition_into_solo = -1;
+ send_signal = true;
+ }
+ }
+
+ update_boolean_masters_records (m);
+
+ if (send_signal) {
+ set_mute_master_solo ();
+ Changed (false, Controllable::UseGroup);
+ }
+
+}
+
+void
+SoloControl::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 (!self_soloed() && !get_boolean_masters()) {
+ _transition_into_solo = 1;
+ Changed (false, Controllable::NoGroup);
+ }
+ }
+}
+
+void
+SoloControl::pre_remove_master (boost::shared_ptr<AutomationControl> m)
+{
+ if (!m) {
+ /* null control ptr means we're removing all masters. Nothing
+ * to do. Changed will be emitted in
+ * SlavableAutomationControl::clear_masters()
+ */
+ return;
+ }
+
+ if (m->get_value()) {
+ if (!self_soloed() && (get_boolean_masters() == 1)) {
+ /* we're not self-soloed, this master is, and we're
+ removing
+ it. SlavableAutomationControl::remove_master() will
+ ensure that we reset our own value after actually
+ removing the master, so that our state does not
+ change (this is a precondition of the
+ SlavableAutomationControl API). This will emit
+ Changed(), and we need to make sure that any
+ listener knows that there has been no transition.
+ */
+ _transition_into_solo = 0;
+ } else {
+ _transition_into_solo = 1;
+ }
+ } else {
+ _transition_into_solo = 0;
+ }
+}
+
+bool
+SoloControl::can_solo () const
+{
+ return _soloable.can_solo ();
+}