some provisional support for "real" solo-isolate behaviour, subject to more discussions with mr. oofus and others
git-svn-id: svn://localhost/ardour2/branches/3.0@6145 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
78503905d7
commit
9fa51e19b6
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include "ardour/route.h"
|
||||
|
||||
#include "gtkmm2ext/cell_renderer_pixbuf_multi.h"
|
||||
#include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
@ -82,27 +83,27 @@ EditorRoutes::EditorRoutes (Editor* e)
|
|||
rec_state_column->add_attribute(rec_col_renderer->property_visible(), _columns.is_track);
|
||||
|
||||
// Mute enable toggle
|
||||
CellRendererPixbufToggle* mute_col_renderer = manage (new CellRendererPixbufToggle());
|
||||
CellRendererPixbufMulti* mute_col_renderer = manage (new CellRendererPixbufMulti());
|
||||
|
||||
mute_col_renderer->set_active_pixbuf (::get_icon("mute-enabled"));
|
||||
mute_col_renderer->set_inactive_pixbuf (::get_icon("act-disabled"));
|
||||
mute_col_renderer->signal_toggled().connect (mem_fun (*this, &EditorRoutes::on_tv_mute_enable_toggled));
|
||||
mute_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
|
||||
mute_col_renderer->set_pixbuf (1, ::get_icon("mute-enabled"));
|
||||
mute_col_renderer->signal_changed().connect (mem_fun (*this, &EditorRoutes::on_tv_mute_enable_toggled));
|
||||
|
||||
Gtk::TreeViewColumn* mute_state_column = manage (new TreeViewColumn("M", *mute_col_renderer));
|
||||
|
||||
mute_state_column->add_attribute(mute_col_renderer->property_active(), _columns.mute_enabled);
|
||||
mute_state_column->add_attribute(mute_col_renderer->property_state(), _columns.mute_state);
|
||||
mute_state_column->add_attribute(mute_col_renderer->property_visible(), _columns.is_track);
|
||||
|
||||
// Solo enable toggle
|
||||
CellRendererPixbufToggle* solo_col_renderer = manage (new CellRendererPixbufToggle());
|
||||
CellRendererPixbufMulti* solo_col_renderer = manage (new CellRendererPixbufMulti());
|
||||
|
||||
solo_col_renderer->set_active_pixbuf (::get_icon("solo-enabled"));
|
||||
solo_col_renderer->set_inactive_pixbuf (::get_icon("act-disabled"));
|
||||
solo_col_renderer->signal_toggled().connect (mem_fun (*this, &EditorRoutes::on_tv_solo_enable_toggled));
|
||||
solo_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
|
||||
solo_col_renderer->set_pixbuf (1, ::get_icon("solo-enabled"));
|
||||
solo_col_renderer->signal_changed().connect (mem_fun (*this, &EditorRoutes::on_tv_solo_enable_toggled));
|
||||
|
||||
Gtk::TreeViewColumn* solo_state_column = manage (new TreeViewColumn("S", *solo_col_renderer));
|
||||
|
||||
solo_state_column->add_attribute(solo_col_renderer->property_active(), _columns.solo_enabled);
|
||||
solo_state_column->add_attribute(solo_col_renderer->property_state(), _columns.solo_state);
|
||||
solo_state_column->add_attribute(solo_col_renderer->property_visible(), _columns.is_track);
|
||||
|
||||
|
||||
|
@ -167,7 +168,6 @@ EditorRoutes::on_tv_rec_enable_toggled (Glib::ustring const & path_string)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EditorRoutes::on_tv_mute_enable_toggled (Glib::ustring const & path_string)
|
||||
{
|
||||
|
@ -182,8 +182,6 @@ EditorRoutes::on_tv_mute_enable_toggled (Glib::ustring const & path_string)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
EditorRoutes::on_tv_solo_enable_toggled (Glib::ustring const & path_string)
|
||||
{
|
||||
|
@ -198,7 +196,6 @@ EditorRoutes::on_tv_solo_enable_toggled (Glib::ustring const & path_string)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EditorRoutes::build_menu ()
|
||||
{
|
||||
|
@ -914,9 +911,9 @@ EditorRoutes::update_mute_display (void* /*src*/)
|
|||
if (boost::dynamic_pointer_cast<Track>(route)) {
|
||||
|
||||
if (route->muted()){
|
||||
(*i)[_columns.mute_enabled] = true;
|
||||
(*i)[_columns.mute_state] = 1;
|
||||
} else {
|
||||
(*i)[_columns.mute_enabled] = false;
|
||||
(*i)[_columns.mute_state] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -934,9 +931,9 @@ EditorRoutes::update_solo_display (void* /*src*/)
|
|||
if (boost::dynamic_pointer_cast<Track>(route)) {
|
||||
|
||||
if (route->soloed()){
|
||||
(*i)[_columns.solo_enabled] = true;
|
||||
(*i)[_columns.solo_state] = 1;
|
||||
} else {
|
||||
(*i)[_columns.solo_enabled] = false;
|
||||
(*i)[_columns.solo_state] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,8 +89,8 @@ private:
|
|||
add (text);
|
||||
add (visible);
|
||||
add (rec_enabled);
|
||||
add (mute_enabled);
|
||||
add (solo_enabled);
|
||||
add (mute_state);
|
||||
add (solo_state);
|
||||
add (is_track);
|
||||
add (tv);
|
||||
add (route);
|
||||
|
@ -99,8 +99,8 @@ private:
|
|||
Gtk::TreeModelColumn<Glib::ustring> text;
|
||||
Gtk::TreeModelColumn<bool> visible;
|
||||
Gtk::TreeModelColumn<bool> rec_enabled;
|
||||
Gtk::TreeModelColumn<bool> mute_enabled;
|
||||
Gtk::TreeModelColumn<bool> solo_enabled;
|
||||
Gtk::TreeModelColumn<uint32_t> mute_state;
|
||||
Gtk::TreeModelColumn<uint32_t> solo_state;
|
||||
Gtk::TreeModelColumn<bool> is_track;
|
||||
Gtk::TreeModelColumn<TimeAxisView*> tv;
|
||||
Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Route> > route;
|
||||
|
|
|
@ -737,16 +737,21 @@ RouteUI::update_mute_display ()
|
|||
|
||||
if (Config->get_show_solo_mutes()) {
|
||||
if (_route->muted()) {
|
||||
/* full mute */
|
||||
mute_button->set_visual_state (2);
|
||||
} else if (!_route->soloed() && _session.soloing()) {
|
||||
} else if (_session.soloing() && !_route->soloed() && !_route->solo_isolated()) {
|
||||
/* mute-because-not-soloed */
|
||||
mute_button->set_visual_state (1);
|
||||
} else {
|
||||
/* no mute at all */
|
||||
mute_button->set_visual_state (0);
|
||||
}
|
||||
} else {
|
||||
if (_route->muted()) {
|
||||
/* full mute */
|
||||
mute_button->set_visual_state (2);
|
||||
} else {
|
||||
/* no mute at all */
|
||||
mute_button->set_visual_state (0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,8 +129,11 @@ class Route : public SessionObject, public AutomatableControls
|
|||
*/
|
||||
|
||||
void set_solo (bool yn, void *src);
|
||||
bool soloed () const { return (bool) _solo_level; }
|
||||
|
||||
bool soloed_by_others () const { return !_solo_isolated && _soloed_by_others; }
|
||||
bool self_soloed () const { return _self_solo; }
|
||||
bool soloed () const {return self_soloed () || soloed_by_others (); }
|
||||
|
||||
void set_solo_isolated (bool yn, void *src);
|
||||
bool solo_isolated() const;
|
||||
|
||||
|
@ -310,8 +313,7 @@ class Route : public SessionObject, public AutomatableControls
|
|||
friend class Session;
|
||||
|
||||
void catch_up_on_solo_mute_override ();
|
||||
void mod_solo_level (int32_t);
|
||||
uint32_t solo_level () const { return _solo_level; }
|
||||
void mod_solo_by_others (int32_t);
|
||||
void set_block_size (nframes_t nframes);
|
||||
bool has_external_redirects() const;
|
||||
void curve_reallocate ();
|
||||
|
@ -347,7 +349,8 @@ class Route : public SessionObject, public AutomatableControls
|
|||
int _pending_declick;
|
||||
MeterPoint _meter_point;
|
||||
uint32_t _phase_invert;
|
||||
uint32_t _solo_level;
|
||||
bool _self_solo;
|
||||
uint32_t _soloed_by_others;
|
||||
bool _solo_isolated;
|
||||
|
||||
bool _denormal_protection;
|
||||
|
@ -411,6 +414,9 @@ class Route : public SessionObject, public AutomatableControls
|
|||
bool add_processor_from_xml_2X (const XMLNode&, int, ProcessorList::iterator iter);
|
||||
|
||||
void placement_range (Placement p, ProcessorList::iterator& start, ProcessorList::iterator& end);
|
||||
|
||||
void set_self_solo (bool yn);
|
||||
void set_delivery_solo ();
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
@ -529,6 +529,7 @@ Delivery::target_gain ()
|
|||
|
||||
gain_t desired_gain;
|
||||
|
||||
|
||||
if (_solo_level) {
|
||||
desired_gain = 1.0;
|
||||
} else {
|
||||
|
@ -549,18 +550,12 @@ Delivery::target_gain ()
|
|||
mp = MuteMaster::PreFader;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_solo_isolated) {
|
||||
|
||||
/* ... but we are isolated from all that nonsense */
|
||||
|
||||
desired_gain = _mute_master->mute_gain_at (mp);
|
||||
|
||||
} else if (_session.soloing()) {
|
||||
|
||||
|
||||
if (!_solo_isolated && _session.soloing()) {
|
||||
desired_gain = min (Config->get_solo_mute_gain(), _mute_master->mute_gain_at (mp));
|
||||
|
||||
} else {
|
||||
|
||||
desired_gain = _mute_master->mute_gain_at (mp);
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,6 @@ IOProcessor::state (bool full_state)
|
|||
node.add_property ("own-output", "yes");
|
||||
if (_output) {
|
||||
XMLNode& o (_output->state (full_state));
|
||||
// o.name() = X_("output");
|
||||
node.add_child_nocopy (o);
|
||||
}
|
||||
} else {
|
||||
|
@ -166,12 +165,21 @@ IOProcessor::set_state (const XMLNode& node, int version)
|
|||
|
||||
XMLNodeList nlist = node.children();
|
||||
XMLNodeIterator niter;
|
||||
const string instr = enum_2_string (IO::Input);
|
||||
const string outstr = enum_2_string (IO::Output);
|
||||
|
||||
if (_own_input) {
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
if ((*niter)->name() == "input") {
|
||||
io_node = (*niter);
|
||||
break;
|
||||
const XMLProperty* prop;
|
||||
if ((prop = (*niter)->property ("name")) != 0) {
|
||||
if (prop->value() == _name) {
|
||||
if ((prop = (*niter)->property ("direction")) != 0) {
|
||||
if (prop->value() == instr) {
|
||||
io_node = (*niter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,16 +192,25 @@ IOProcessor::set_state (const XMLNode& node, int version)
|
|||
}
|
||||
|
||||
} else {
|
||||
/* no input */
|
||||
/* no input, which is OK */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (_own_output) {
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
if ((*niter)->name() == "output") {
|
||||
io_node = (*niter);
|
||||
break;
|
||||
if ((*niter)->name() == "IO") {
|
||||
const XMLProperty* prop;
|
||||
if ((prop = (*niter)->property ("name")) != 0) {
|
||||
if (prop->value() == _name) {
|
||||
if ((prop = (*niter)->property ("direction")) != 0) {
|
||||
if (prop->value() == outstr) {
|
||||
io_node = (*niter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,7 +222,7 @@ IOProcessor::set_state (const XMLNode& node, int version)
|
|||
set_name (_output->name());
|
||||
}
|
||||
} else {
|
||||
/* no output */
|
||||
/* no output, which is OK */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -116,11 +116,12 @@ Route::Route (Session& sess, const XMLNode& node, DataType default_type)
|
|||
void
|
||||
Route::init ()
|
||||
{
|
||||
_solo_level = 0;
|
||||
_self_solo = false;
|
||||
_soloed_by_others = 0;
|
||||
_solo_isolated = false;
|
||||
_solo_safe = false;
|
||||
_active = true;
|
||||
processor_max_streams.reset();
|
||||
_solo_safe = false;
|
||||
_recordable = true;
|
||||
order_keys[N_("signal")] = order_key_cnt++;
|
||||
_silent = false;
|
||||
|
@ -523,7 +524,7 @@ Route::listening () const
|
|||
void
|
||||
Route::set_solo (bool yn, void *src)
|
||||
{
|
||||
if (_solo_safe || _solo_isolated) {
|
||||
if (_solo_safe) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -532,40 +533,51 @@ Route::set_solo (bool yn, void *src)
|
|||
return;
|
||||
}
|
||||
|
||||
if (soloed() != yn) {
|
||||
mod_solo_level (yn ? 1 : -1);
|
||||
if (self_soloed() != yn) {
|
||||
set_self_solo (yn);
|
||||
set_delivery_solo ();
|
||||
solo_changed (src); /* EMIT SIGNAL */
|
||||
_solo_control->Changed (); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Route::mod_solo_level (int32_t delta)
|
||||
Route::set_self_solo (bool yn)
|
||||
{
|
||||
_self_solo = yn;
|
||||
}
|
||||
|
||||
void
|
||||
Route::mod_solo_by_others (int32_t delta)
|
||||
{
|
||||
if (delta < 0) {
|
||||
if (_solo_level >= (uint32_t) delta) {
|
||||
_solo_level += delta;
|
||||
if (_soloed_by_others >= (uint32_t) delta) {
|
||||
_soloed_by_others += delta;
|
||||
} else {
|
||||
_solo_level = 0;
|
||||
_soloed_by_others = 0;
|
||||
}
|
||||
} else {
|
||||
_solo_level += delta;
|
||||
_soloed_by_others += delta;
|
||||
}
|
||||
|
||||
{
|
||||
/* tell all delivery processors what the solo situation is, so that they keep
|
||||
delivering even though Session::soloing() is true and they were not
|
||||
explicitly soloed.
|
||||
*/
|
||||
|
||||
Glib::RWLock::ReaderLock rm (_processor_lock);
|
||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||
boost::shared_ptr<Delivery> d;
|
||||
set_delivery_solo ();
|
||||
}
|
||||
|
||||
if ((d = boost::dynamic_pointer_cast<Delivery> (*i)) != 0) {
|
||||
d->set_solo_level (_solo_level);
|
||||
d->set_solo_isolated (_solo_isolated);
|
||||
}
|
||||
void
|
||||
Route::set_delivery_solo ()
|
||||
{
|
||||
/* tell all delivery processors what the solo situation is, so that they keep
|
||||
delivering even though Session::soloing() is true and they were not
|
||||
explicitly soloed.
|
||||
*/
|
||||
|
||||
Glib::RWLock::ReaderLock rm (_processor_lock);
|
||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||
boost::shared_ptr<Delivery> d;
|
||||
|
||||
if ((d = boost::dynamic_pointer_cast<Delivery> (*i)) != 0) {
|
||||
d->set_solo_level (soloed ());
|
||||
d->set_solo_isolated (solo_isolated());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -580,13 +592,7 @@ Route::set_solo_isolated (bool yn, void *src)
|
|||
|
||||
if (yn != _solo_isolated) {
|
||||
_solo_isolated = yn;
|
||||
|
||||
/* tell main outs what the solo situation is
|
||||
*/
|
||||
|
||||
_main_outs->set_solo_level (_solo_level);
|
||||
_main_outs->set_solo_isolated (_solo_isolated);
|
||||
|
||||
set_delivery_solo ();
|
||||
solo_isolated_changed (src);
|
||||
}
|
||||
}
|
||||
|
@ -1679,6 +1685,9 @@ Route::state(bool full_state)
|
|||
order_string += ':';
|
||||
}
|
||||
node->add_property ("order-keys", order_string);
|
||||
node->add_property ("self-solo", (_self_solo ? "yes" : "no"));
|
||||
snprintf (buf, sizeof (buf), "%d", _soloed_by_others);
|
||||
node->add_property ("soloed-by-others", buf);
|
||||
|
||||
node->add_child_nocopy (_input->state (full_state));
|
||||
node->add_child_nocopy (_output->state (full_state));
|
||||
|
@ -1772,9 +1781,13 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/)
|
|||
|
||||
set_processor_state (processor_state);
|
||||
|
||||
if ((prop = node.property ("solo_level")) != 0) {
|
||||
_solo_level = 0; // needed for mod_solo_level() to work
|
||||
mod_solo_level (atoi (prop->value()));
|
||||
if ((prop = node.property ("self-solo")) != 0) {
|
||||
set_self_solo (string_is_affirmative (prop->value()));
|
||||
}
|
||||
|
||||
if ((prop = node.property ("soloed-by-others")) != 0) {
|
||||
_soloed_by_others = 0; // needed for mod_solo_by_others () to work
|
||||
mod_solo_by_others (atoi (prop->value()));
|
||||
}
|
||||
|
||||
if ((prop = node.property ("solo-isolated")) != 0) {
|
||||
|
@ -1795,14 +1808,6 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/)
|
|||
set_active (yn);
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("soloed"))) != 0) {
|
||||
bool yn = string_is_affirmative (prop->value());
|
||||
|
||||
/* XXX force reset of solo status */
|
||||
|
||||
set_solo (yn, this);
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("meter-point"))) != 0) {
|
||||
_meter_point = MeterPoint (string_2_enum (prop->value (), _meter_point));
|
||||
if (_meter) {
|
||||
|
@ -2830,7 +2835,7 @@ Route::SoloControllable::set_value (float val)
|
|||
float
|
||||
Route::SoloControllable::get_value (void) const
|
||||
{
|
||||
return route.soloed() ? 1.0f : 0.0f;
|
||||
return route.self_soloed() ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -2426,7 +2426,7 @@ Session::route_solo_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
|
|||
shared_ptr<RouteList> r = routes.reader ();
|
||||
int32_t delta;
|
||||
|
||||
if (route->soloed()) {
|
||||
if (route->self_soloed()) {
|
||||
delta = 1;
|
||||
} else {
|
||||
delta = -1;
|
||||
|
@ -2437,27 +2437,30 @@ Session::route_solo_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
|
|||
*/
|
||||
|
||||
solo_update_disabled = true;
|
||||
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
bool via_sends_only;
|
||||
|
||||
if ((*i)->feeds (route, &via_sends_only) && !(*i)->is_hidden() && !(*i)->is_master() && !(*i)->is_control()) {
|
||||
|
||||
if ((*i) == route || !(*i)->solo_isolated() || !(*i)->is_master() || !(*i)->is_control() || (*i)->is_hidden()) {
|
||||
continue;
|
||||
} else if ((*i)->feeds (route, &via_sends_only)) {
|
||||
if (!via_sends_only) {
|
||||
/* do it */
|
||||
(*i)->mod_solo_level (delta);
|
||||
}
|
||||
}
|
||||
(*i)->mod_solo_by_others (delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* make sure master is never muted by solo */
|
||||
|
||||
if (_master_out && route != _master_out && _master_out->solo_level() == 0 && !_master_out->soloed()) {
|
||||
_master_out->mod_solo_level (1);
|
||||
}
|
||||
|
||||
if (_master_out && route != _master_out && _master_out->soloed_by_others() == 0 && !_master_out->soloed()) {
|
||||
_master_out->mod_solo_by_others (1);
|
||||
}
|
||||
|
||||
/* ditto for control outs make sure master is never muted by solo */
|
||||
|
||||
if (_control_out && route != _control_out && _control_out && _control_out->solo_level() == 0) {
|
||||
_control_out->mod_solo_level (1);
|
||||
if (_control_out && route != _control_out && _control_out && _control_out->soloed_by_others() == 0) {
|
||||
_control_out->mod_solo_by_others (1);
|
||||
}
|
||||
|
||||
solo_update_disabled = false;
|
||||
|
@ -2478,7 +2481,7 @@ Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
|
|||
}
|
||||
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
if (!(*i)->is_master() && !(*i)->is_control() && !(*i)->is_hidden() && (*i)->soloed()) {
|
||||
if (!(*i)->is_master() && !(*i)->is_control() && !(*i)->is_hidden() && (*i)->self_soloed()) {
|
||||
something_soloed = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ gtkmm2ext_sources = [
|
|||
'auto_spin.cc',
|
||||
'barcontroller.cc',
|
||||
'binding_proxy.cc',
|
||||
'cell_renderer_pixbuf_multi.cc',
|
||||
'cell_renderer_pixbuf_toggle.cc',
|
||||
'choice.cc',
|
||||
'click_box.cc',
|
||||
|
|
Loading…
Reference in New Issue