[Summary] Apply Solo, Exclusive Solo, Momentary Solo and Solo isolated to all selected tracks

[Feature reviewed] MKosharnyy
[Reviewed] GZharun
This commit is contained in:
Nikolay 2015-01-21 18:25:28 +02:00
parent bd7bb37206
commit 0655bd6d9a
7 changed files with 275 additions and 65 deletions

View file

@ -161,6 +161,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
bool self_soloed () const { return _self_solo; }
void set_solo_isolated (bool yn, void *src);
void set_solo_isolated_force (bool yn, void *src);
bool solo_isolated() const;
void set_solo_safe (bool yn, void *src);
@ -521,6 +522,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
uint32_t _soloed_by_others_upstream;
uint32_t _soloed_by_others_downstream;
uint32_t _solo_isolated;
bool _forced_solo_isolated;
bool _denormal_protection;

View file

@ -697,6 +697,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
void set_listen (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
void set_record_enabled (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
void set_solo_isolated (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
void set_solo_isolated_force (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
void set_monitoring (boost::shared_ptr<RouteList>, MonitorChoice, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
void set_exclusive_input_active (boost::shared_ptr<RouteList> rt, bool onoff, bool flip_others=false);
@ -1464,6 +1465,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
void route_listen_changed (void *src, boost::weak_ptr<Route>);
void route_mute_changed (void *src);
void route_solo_changed (bool self_solo_change, void *src, boost::weak_ptr<Route>);
void routes_solo_changed (boost::shared_ptr<RouteList> solo_change_routes);
void route_solo_isolated_changed (void *src, boost::weak_ptr<Route>);
void update_route_solo_state (boost::shared_ptr<RouteList> r = boost::shared_ptr<RouteList>());
@ -1702,6 +1704,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
void rt_set_mute (boost::shared_ptr<RouteList>, bool yn, bool group_override);
void rt_set_listen (boost::shared_ptr<RouteList>, bool yn, bool group_override);
void rt_set_solo_isolated (boost::shared_ptr<RouteList>, bool yn, bool group_override);
void rt_set_solo_isolated_force (boost::shared_ptr<RouteList>, bool yn, bool group_override);
void rt_set_record_enabled (boost::shared_ptr<RouteList>, bool yn, bool group_override);
void rt_set_monitoring (boost::shared_ptr<RouteList>, MonitorChoice, bool group_override);

View file

@ -921,6 +921,12 @@ Route::set_solo_isolated (bool yn, void *src)
_solo_isolated++;
} else {
if (_solo_isolated > 0) {
// do not drop to 0 if we are forced to be in solo isolated mode
if (_forced_solo_isolated && _solo_isolated == 1) {
return;
}
_solo_isolated--;
if (_solo_isolated == 0) {
_mute_master->set_solo_ignore (false);
@ -934,6 +940,43 @@ Route::set_solo_isolated (bool yn, void *src)
}
}
void
Route::set_solo_isolated_force (bool yn, void *src)
{
if (is_master() || is_monitor() || is_auditioner()) {
return;
}
bool changed = false;
if (yn)
{
_forced_solo_isolated = true;
if (_solo_isolated == 0) {
_solo_isolated++;
_mute_master->set_solo_ignore (true);
changed = true;
} else {
return;
}
} else {
_forced_solo_isolated = false;
if (_solo_isolated > 0) {
_solo_isolated--;
if (_solo_isolated == 0) {
_mute_master->set_solo_ignore (false);
changed = true;
}
}
}
if (changed) {
solo_isolated_changed (src);
}
}
bool
Route::solo_isolated () const
{

View file

@ -3397,6 +3397,7 @@ Session::route_listen_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
update_route_solo_state ();
}
void
Session::route_solo_isolated_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
{
@ -3558,6 +3559,120 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
set_dirty();
}
void
Session::routes_solo_changed (boost::shared_ptr<RouteList> solo_change_routes)
{
if (solo_update_disabled) {
// We know already
DEBUG_TRACE (DEBUG::Solo, "solo update disabled - changed ignored\n");
return;
}
if (solo_change_routes->empty() ) {
return;
}
boost::shared_ptr<RouteList> non_solo_change_routes (new RouteList);
boost::shared_ptr<RouteList> r = routes.reader ();
int32_t delta;
std::set_difference (r->begin(), r->end(),
solo_change_routes->begin(), solo_change_routes->end(),
std::back_inserter(*non_solo_change_routes) );
DEBUG_TRACE (DEBUG::Solo, string_compose ("propagate solo change, delta = %1\n", delta));
solo_update_disabled = true;
RouteList uninvolved;
for (RouteList::iterator route = solo_change_routes->begin(); route != solo_change_routes->begin(); ++route) {
if ((*route)->self_soloed() ) {
delta = 1;
} else {
delta = -1;
}
DEBUG_TRACE (DEBUG::Solo, string_compose ("%1\n", (*route)->name()));
for (RouteList::iterator i = non_solo_change_routes->begin(); i != non_solo_change_routes->end(); ++i) {
bool via_sends_only;
bool in_signal_flow;
if ((*i) == *route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner() ) {
continue;
}
in_signal_flow = false;
DEBUG_TRACE (DEBUG::Solo, string_compose ("check feed from %1\n", (*i)->name()));
if ((*i)->feeds (*route, &via_sends_only)) {
DEBUG_TRACE (DEBUG::Solo, string_compose ("\tthere is a feed from %1\n", (*i)->name()));
if (!via_sends_only) {
if (!(*route)->soloed_by_others_upstream()) {
(*i)->mod_solo_by_others_downstream (delta);
}
} else {
DEBUG_TRACE (DEBUG::Solo, string_compose ("\tthere is a send-only feed from %1\n", (*i)->name()));
}
in_signal_flow = true;
} else {
DEBUG_TRACE (DEBUG::Solo, string_compose ("\tno feed from %1\n", (*i)->name()));
}
DEBUG_TRACE (DEBUG::Solo, string_compose ("check feed to %1\n", (*i)->name()));
if ((*route)->feeds (*i, &via_sends_only)) {
/* propagate solo upstream only if routing other than
sends is involved, but do consider the other route
(*i) to be part of the signal flow even if only
sends are involved.
*/
DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 feeds %2 via sends only %3 sboD %4 sboU %5\n",
(*route)->name(),
(*i)->name(),
via_sends_only,
(*route)->soloed_by_others_downstream(),
(*route)->soloed_by_others_upstream()));
if (!via_sends_only) {
if (!(*route)->soloed_by_others_downstream()) {
DEBUG_TRACE (DEBUG::Solo, string_compose ("\tmod %1 by %2\n", (*i)->name(), delta));
(*i)->mod_solo_by_others_upstream (delta);
} else {
DEBUG_TRACE (DEBUG::Solo, "\talready soloed by others downstream\n");
}
} else {
DEBUG_TRACE (DEBUG::Solo, string_compose ("\tfeed to %1 ignored, sends-only\n", (*i)->name()));
}
in_signal_flow = true;
} else {
DEBUG_TRACE (DEBUG::Solo, "\tno feed to\n");
}
if (!in_signal_flow) {
uninvolved.push_back (*i);
}
}
}
solo_update_disabled = false;
DEBUG_TRACE (DEBUG::Solo, "propagation complete\n");
update_route_solo_state ();
/* now notify that the mute state of the routes not involved in the signal
pathway of the just-solo-changed route may have altered.
*/
for (RouteList::iterator i = uninvolved.begin(); i != uninvolved.end(); ++i) {
DEBUG_TRACE (DEBUG::Solo, string_compose ("mute change for %1\n", (*i)->name() ));
(*i)->mute_changed (this);
}
SoloChanged (); /* EMIT SIGNAL */
set_dirty();
}
void
Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
{

View file

@ -62,12 +62,15 @@ Session::set_solo (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeve
void
Session::rt_set_solo (boost::shared_ptr<RouteList> rl, bool yn, bool /* group_override */)
{
solo_update_disabled = true;
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
if (!(*i)->is_auditioner()) {
(*i)->set_solo (yn, this);
}
}
solo_update_disabled = false;
routes_solo_changed (rl);
set_dirty();
}
@ -176,6 +179,24 @@ Session::rt_set_solo_isolated (boost::shared_ptr<RouteList> rl, bool yn, bool /*
set_dirty();
}
void
Session::set_solo_isolated_force (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
{
queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_solo_isolated_force));
}
void
Session::rt_set_solo_isolated_force (boost::shared_ptr<RouteList> rl, bool yn, bool /*group_override*/)
{
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_auditioner()) {
(*i)->set_solo_isolated_force (yn, this);
}
}
set_dirty();
}
void
Session::set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
{