some provisional support for "real" solo-isolate behaviour, subject to more discussio...
authorPaul Davis <paul@linuxaudiosystems.com>
Sat, 21 Nov 2009 17:20:57 +0000 (17:20 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Sat, 21 Nov 2009 17:20:57 +0000 (17:20 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@6145 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/editor_routes.cc
gtk2_ardour/editor_routes.h
gtk2_ardour/route_ui.cc
libs/ardour/ardour/route.h
libs/ardour/delivery.cc
libs/ardour/io_processor.cc
libs/ardour/route.cc
libs/ardour/session.cc
libs/gtkmm2ext/wscript

index 35eec34c7597750bb39ff2e9719c6093a873b46f..8feebe9df3d030d192ae2c0557c5b729b42386e7 100644 (file)
@@ -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;
                        }
                }
        }
index 72554129c8720dd3b1b930638075a269684fe6ce..0a8947fdd1dc17570e78197ec1255add90b2be72 100644 (file)
@@ -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;
index e06b9b18c4327c462193defff0fbc1e67eac0939..95cb6b66efc6b44a2ffd301cadc1dc5facfed62d 100644 (file)
@@ -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);
                }
        }
index 1a60e2f8cd7a093215d72a8a1057a24d450626f9..db67cab17bbde3064deb3f85fda780a7ccbadd86 100644 (file)
@@ -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
index 113c43438822f7a88a1f8f88ee18cdc08b7f63af..72f24c065e50b7f54214112d927b806e07ea6776 100644 (file)
@@ -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);
                }
 
index 21a2b10313d4be15afcdf727b0f227669aa90508..6bdac9fe199e47f6b0064f351ac5a63b7cc10d55 100644 (file)
@@ -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 */
                }
        }
 
index d6f740e33c668b02da7405e852f238dfb22ad50d..372e9ade6881b6ad8bd6b9e0ecbc164dad0ea1cd 100644 (file)
@@ -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
index 0d5cdcacb5869c2b2e15780de9961d76bd5f2747..ce1fbca84624fe5410e70f92a0412dc09ecd0f35 100644 (file)
@@ -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;
                }
index 7c8f4cda99de6372195aa02096355f8eed49737e..5ca8d5344d6fde3d64bb2acfcdd10f3b7d464fa1 100644 (file)
@@ -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',