first compiling, mostly working version of group controls changes
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 21 Jan 2016 16:03:14 +0000 (11:03 -0500)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 22 Jan 2016 16:58:31 +0000 (11:58 -0500)
33 files changed:
gtk2_ardour/ardour_ui.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_routes.cc
gtk2_ardour/editor_routes.h
gtk2_ardour/mixer_strip.cc
gtk2_ardour/monitor_section.cc
gtk2_ardour/route_ui.cc
gtk2_ardour/route_ui.h
libs/ardour/ardour/gain_control.h
libs/ardour/ardour/midi_track.h
libs/ardour/ardour/pan_controllable.h
libs/ardour/ardour/plugin_insert.h
libs/ardour/ardour/route.h
libs/ardour/ardour/route_group.h
libs/ardour/ardour/route_group_member.h
libs/ardour/ardour/route_group_specialized.h
libs/ardour/ardour/session.h
libs/ardour/ardour/track.h
libs/ardour/gain_control.cc
libs/ardour/midi_track.cc
libs/ardour/pan_controllable.cc
libs/ardour/plugin_insert.cc
libs/ardour/route.cc
libs/ardour/route_group_member.cc
libs/ardour/session.cc
libs/ardour/session_midi.cc
libs/ardour/session_rtevents.cc
libs/ardour/track.cc
libs/surfaces/control_protocol/control_protocol.cc
libs/surfaces/faderport/faderport.cc
libs/surfaces/faderport/faderport.h
libs/surfaces/mackie/strip.cc
libs/surfaces/osc/osc.cc

index 1ea6700b521a0013b68c930d49ca3eff164109cf..4d6a0a72d5caabe2d0aae86d34537e4a0166cb70 100644 (file)
@@ -2247,10 +2247,10 @@ ARDOUR_UI::toggle_record_enable (uint32_t rid)
 
        if ((r = _session->route_by_remote_id (rid)) != 0) {
 
-               Track* t;
+               boost::shared_ptr<Track> t;
 
-               if ((t = dynamic_cast<Track*>(r.get())) != 0) {
-                       t->set_record_enabled (!t->record_enabled(), this);
+               if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
+                       t->set_record_enabled (!t->record_enabled(), Controllable::UseGroup);
                }
        }
 }
index 814cded54130c8e1b3db16d7517819c02d049eb4..55d38f3a884e9da23d7f2346a77a30eee84cbc22 100644 (file)
@@ -5701,7 +5701,7 @@ Editor::toggle_record_enable ()
                        first = false;
                }
 
-               rtav->track()->set_record_enabled (new_state, this);
+               rtav->track()->set_record_enabled (new_state, Controllable::UseGroup);
        }
 }
 
@@ -5727,7 +5727,7 @@ Editor::toggle_solo ()
                rl->push_back (rtav->route());
        }
 
-       _session->set_solo (rl, new_state, Session::rt_cleanup, true);
+       _session->set_solo (rl, new_state, Session::rt_cleanup, Controllable::UseGroup);
 }
 
 void
@@ -5752,7 +5752,7 @@ Editor::toggle_mute ()
                rl->push_back (rtav->route());
        }
 
-       _session->set_mute (rl, new_state, Session::rt_cleanup, true);
+       _session->set_mute (rl, new_state, Session::rt_cleanup, Controllable::UseGroup);
 }
 
 void
index 588b900f192b3b7a875b5fd93a7bdbf517712d4b..e4a48db5af62aea5fa4fecb263dcc1f1a3886994 100644 (file)
@@ -453,7 +453,7 @@ EditorRoutes::on_tv_solo_isolate_toggled (std::string const & path_string)
        RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
 
        if (rtv) {
-               rtv->route()->set_solo_isolated (!rtv->route()->solo_isolated(), this);
+               rtv->route()->set_solo_isolated (!rtv->route()->solo_isolated(), Controllable::UseGroup);
        }
 }
 
@@ -467,7 +467,7 @@ EditorRoutes::on_tv_solo_safe_toggled (std::string const & path_string)
        RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
 
        if (rtv) {
-               rtv->route()->set_solo_safe (!rtv->route()->solo_safe(), this);
+               rtv->route()->set_solo_safe (!rtv->route()->solo_safe(), Controllable::UseGroup);
        }
 }
 
@@ -711,8 +711,8 @@ EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
                }
 
                (*x)->route()->mute_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_mute_display, this), gui_context());
-               (*x)->route()->solo_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_display, this, _1), gui_context());
-               (*x)->route()->listen_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_display, this, _1), gui_context());
+               (*x)->route()->solo_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_display, this), gui_context());
+               (*x)->route()->listen_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_display, this), gui_context());
                (*x)->route()->solo_isolated_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_isolate_display, this), gui_context());
                (*x)->route()->solo_safe_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_safe_display, this), gui_context());
                (*x)->route()->active_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_active_display, this), gui_context ());
@@ -721,7 +721,7 @@ EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
 
        update_rec_display ();
        update_mute_display ();
-       update_solo_display (true);
+       update_solo_display ();
        update_solo_isolate_display ();
        update_solo_safe_display ();
        update_input_active_display ();
@@ -1632,7 +1632,7 @@ EditorRoutes::update_mute_display ()
 }
 
 void
-EditorRoutes::update_solo_display (bool /* selfsoloed */)
+EditorRoutes::update_solo_display ()
 {
        if (g_atomic_int_compare_and_exchange (&_queue_tv_update, 0, 1)) {
                Glib::signal_idle().connect (sigc::mem_fun (*this, &EditorRoutes::idle_update_mute_rec_solo_etc));
index 94a2186a4c70eb3b053720e1b88b06e39165f47e..bee37378fb9683ea1d264653505d06f40427b313 100644 (file)
@@ -86,7 +86,7 @@ private:
        bool idle_update_mute_rec_solo_etc ();
        void update_rec_display ();
        void update_mute_display ();
-       void update_solo_display (bool);
+       void update_solo_display ();
        void update_solo_isolate_display ();
        void update_solo_safe_display ();
        void update_input_active_display ();
index 5247d89033c1ff401555f1ad79ffa6ce29d7364a..64b4494bac8e11f62b47a389b03e11f7bc12256c 100644 (file)
@@ -637,7 +637,7 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
        update_mute_display ();
        update_solo_display ();
        name_changed ();
-       comment_changed (0);
+       comment_changed ();
        route_group_changed ();
 
        connect_to_pan ();
index 0741bffa5d3712e712cb4f03af6e28454c3e4bd2..d07ca51dd56b1a35367da8728d4cdca06168ef97 100644 (file)
@@ -1210,7 +1210,7 @@ MonitorSection::cancel_isolate (GdkEventButton*)
 {
        if (_session) {
                boost::shared_ptr<RouteList> rl (_session->get_routes ());
-               _session->set_solo_isolated (rl, false, Session::rt_cleanup, true);
+               _session->set_solo_isolated (rl, false, Session::rt_cleanup, Controllable::NoGroup);
        }
 
        return true;
index 059f20a885b05d0c0bdb7e269c9b33f61ffdcc5a..ddba45b73f3359ac7511807f1c19b5ca59b64509 100644 (file)
@@ -259,7 +259,7 @@ RouteUI::set_route (boost::shared_ptr<Route> rp)
        _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
        _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_mute_display, this), gui_context());
 
-       _route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::comment_changed, this, _1), gui_context());
+       _route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::comment_changed, this), gui_context());
 
        _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
        _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
@@ -426,7 +426,7 @@ RouteUI::mute_press (GdkEventButton* ev)
                                        }
 
                                        DisplaySuspender ds;
-                                       _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
+                                       _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, Controllable::WholeGroup);
                                }
 
                        } else {
@@ -454,7 +454,7 @@ RouteUI::mute_release (GdkEventButton* /*ev*/)
 {
        if (_mute_release){
                DisplaySuspender ds;
-               _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
+               _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, Controllable::UseGroup);
                delete _mute_release;
                _mute_release = 0;
        }
@@ -555,9 +555,9 @@ RouteUI::solo_press(GdkEventButton* ev)
 
                                DisplaySuspender ds;
                                if (Config->get_solo_control_is_listen_control()) {
-                                       _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(),  Session::rt_cleanup, false);
+                                       _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(),  Session::rt_cleanup, Controllable::NoGroup);
                                } else {
-                                       _session->set_solo (_session->get_routes(), !_route->self_soloed(),  Session::rt_cleanup, false);
+                                       _session->set_solo (_session->get_routes(), !_route->self_soloed(),  Session::rt_cleanup, Controllable::NoGroup);
                                }
 
                        } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
@@ -589,7 +589,7 @@ RouteUI::solo_press(GdkEventButton* ev)
 
                                // shift-click: toggle solo isolated status
 
-                               _route->set_solo_isolated (!_route->solo_isolated(), this);
+                               _route->set_solo_isolated (!_route->solo_isolated(), Controllable::UseGroup);
                                delete _solo_release;
                                _solo_release = 0;
 
@@ -620,9 +620,9 @@ RouteUI::solo_press(GdkEventButton* ev)
 
                                        DisplaySuspender ds;
                                        if (Config->get_solo_control_is_listen_control()) {
-                                               _session->set_listen (rl, !_route->listening_via_monitor(),  Session::rt_cleanup, true);
+                                               _session->set_listen (rl, !_route->listening_via_monitor(),  Session::rt_cleanup, Controllable::WholeGroup);
                                        } else {
-                                               _session->set_solo (rl, !_route->self_soloed(),  Session::rt_cleanup, true);
+                                               _session->set_solo (rl, !_route->self_soloed(),  Session::rt_cleanup, Controllable::WholeGroup);
                                        }
                                }
 
@@ -663,9 +663,9 @@ RouteUI::solo_release (GdkEventButton* /*ev*/)
                } else {
                        DisplaySuspender ds;
                        if (Config->get_solo_control_is_listen_control()) {
-                               _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, false);
+                               _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, Controllable::UseGroup);
                        } else {
-                               _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, false);
+                               _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, Controllable::UseGroup);
                        }
                }
 
@@ -735,7 +735,7 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
                                }
 
                                DisplaySuspender ds;
-                               _session->set_record_enabled (rl, !_route->record_enabled(), Session::rt_cleanup, true);
+                               _session->set_record_enabled (rl, !_route->record_enabled(), Session::rt_cleanup, Controllable::WholeGroup);
                        }
 
                } else if (Keyboard::is_context_menu_event (ev)) {
@@ -865,7 +865,7 @@ RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
        }
 
        DisplaySuspender ds;
-       _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
+       _session->set_monitoring (rl, mc, Session::rt_cleanup, Controllable::UseGroup);
 
        return false;
 }
@@ -1437,11 +1437,11 @@ RouteUI::solo_isolate_button_release (GdkEventButton* ev)
                        if (model) {
                                /* disable isolate for all routes */
                                DisplaySuspender ds;
-                               _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
+                               _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, Controllable::NoGroup);
                        } else {
                                /* enable isolate for all routes */
                                DisplaySuspender ds;
-                               _session->set_solo_isolated (_session->get_routes(), true, Session::rt_cleanup, true);
+                               _session->set_solo_isolated (_session->get_routes(), true, Session::rt_cleanup, Controllable::NoGroup);
                        }
 
                } else {
@@ -1453,7 +1453,7 @@ RouteUI::solo_isolate_button_release (GdkEventButton* ev)
                                boost::shared_ptr<RouteList> rl (new RouteList);
                                rl->push_back (_route);
                                DisplaySuspender ds;
-                               _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
+                               _session->set_solo_isolated (rl, !view, Session::rt_cleanup, Controllable::NoGroup);
                        }
                }
        }
@@ -1478,20 +1478,20 @@ RouteUI::solo_safe_button_release (GdkEventButton* ev)
                                /* disable solo safe for all routes */
                                DisplaySuspender ds;
                                for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
-                                       (*i)->set_solo_safe (false, this);
+                                       (*i)->set_solo_safe (false, Controllable::NoGroup);
                                }
                        } else {
                                /* enable solo safe for all routes */
                                DisplaySuspender ds;
                                for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
-                                       (*i)->set_solo_safe (true, this);
+                                       (*i)->set_solo_safe (true, Controllable::NoGroup);
                                }
                        }
                }
                else {
                        if (model == view) {
                                /* flip just this route */
-                               _route->set_solo_safe (!view, this);
+                               _route->set_solo_safe (!view, Controllable::NoGroup);
                        }
                }
        }
@@ -1508,14 +1508,14 @@ RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
         /* called AFTER the view has changed */
 
         if (model != view) {
-                _route->set_solo_isolated (view, this);
+               _route->set_solo_isolated (view, Controllable::UseGroup);
         }
 }
 
 void
 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
 {
-       _route->set_solo_safe (check->get_active(), this);
+       _route->set_solo_safe (check->get_active(), Controllable::UseGroup);
 }
 
 /** Ask the user to choose a colour, and then apply that color to my route
@@ -1702,17 +1702,13 @@ RouteUI::setup_comment_editor ()
 }
 
 void
-RouteUI::comment_changed (void *src)
+RouteUI::comment_changed ()
 {
-       ENSURE_GUI_THREAD (*this, &MixerStrip::comment_changed, src)
-
-       if (src != this) {
-               ignore_comment_edit = true;
-               if (comment_area) {
-                       comment_area->get_buffer()->set_text (_route->comment());
-               }
-               ignore_comment_edit = false;
+       ignore_comment_edit = true;
+       if (comment_area) {
+               comment_area->get_buffer()->set_text (_route->comment());
        }
+       ignore_comment_edit = false;
 }
 
 void
index ff4d45300f843b9d8ad775c0bfc645d491aacab1..461419c8480d1b7f13ceade57554aeb753e2f8fd 100644 (file)
@@ -241,7 +241,7 @@ class RouteUI : public virtual AxisView
        void toggle_comment_editor ();
 
        gint comment_key_release_handler (GdkEventKey*);
-       void comment_changed (void *src);
+       void comment_changed ();
        void comment_edited ();
        bool ignore_comment_edit;
 
index 17c250151a1291c0030ce7eff11356a689bca757..07a900a164ddb3322145e515a0f38203eb67d4a0 100644 (file)
@@ -33,7 +33,8 @@ namespace ARDOUR {
 
 class Session;
 
-struct LIBARDOUR_API GainControl : public AutomationControl {
+class LIBARDOUR_API GainControl : public AutomationControl {
+  public:
        GainControl (Session& session, const Evoral::Parameter &param,
                     boost::shared_ptr<AutomationList> al = boost::shared_ptr<AutomationList>());
 
@@ -48,6 +49,8 @@ struct LIBARDOUR_API GainControl : public AutomationControl {
 
        double lower_db;
        double range_db;
+  private:
+       void _set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
 };
 
 } /* namespace */
index ba418082f88d391180263eebf876f46d146d61ad..a007757679e19bdb7701660ad1c472e3006094da 100644 (file)
@@ -50,8 +50,8 @@ public:
 
        boost::shared_ptr<Diskstream> create_diskstream ();
        void set_diskstream (boost::shared_ptr<Diskstream>);
-       void set_record_enabled (bool yn, void *src);
-       void set_record_safe (bool yn, void *src);
+       void set_record_enabled (bool yn, PBD::Controllable::GroupControlDisposition);
+       void set_record_safe (bool yn, PBD::Controllable::GroupControlDisposition);
 
        DataType data_type () const {
                return DataType::MIDI;
@@ -94,6 +94,9 @@ public:
                bool writable() const { return true; }
 
                MidiTrack* _route;
+
+       private:
+               void _set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
        };
 
        virtual void set_parameter_automation_state (Evoral::Parameter param, AutoState);
index 77acbee04ff4e0bf49b43d70e456b9ba2173b43e..85a4efe2fc17dbace82686bb80abc63b422f32a5 100644 (file)
@@ -52,6 +52,7 @@ class LIBARDOUR_API PanControllable : public AutomationControl
 
   private:
        Pannable* owner;
+       void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
 };
 
 } // namespace
index 6b434bef7f0db7d30e5859525f94a51cde1344fb..ffa55b9eaa4bafc4184a930b00bf4613a3e2c5f1 100644 (file)
@@ -103,6 +103,7 @@ class LIBARDOUR_API PluginInsert : public Processor
 
        private:
                PluginInsert* _plugin;
+               void _set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
        };
 
        /** A control that manipulates a plugin property (message). */
index e3eec7107843cf0a5941c223e9b9e3c70795c656..5351d8490a682fce4f0de32d1a93e13ed56afbca 100644 (file)
@@ -128,9 +128,9 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 
        virtual bool can_record() { return false; }
 
-       virtual void set_record_enabled (bool /*yn*/, void * /*src*/) {}
+       virtual void set_record_enabled (bool /*yn*/, PBD::Controllable::GroupControlDisposition) {}
        virtual bool record_enabled() const { return false; }
-       virtual void set_record_safe (bool yn, void *src) {}
+       virtual void set_record_safe (bool /*yn*/, PBD::Controllable::GroupControlDisposition) {}
        virtual bool record_safe () const {return false; }
        virtual void nonrealtime_handle_transport_stopped (bool abort, bool did_locate, bool flush_processors);
        virtual void realtime_handle_transport_stopped () {}
@@ -145,20 +145,20 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        void set_gain (gain_t val, PBD::Controllable::GroupControlDisposition);
        void inc_gain (gain_t delta);
 
-       void set_trim (gain_t val, void *src);
+       void set_trim (gain_t val, PBD::Controllable::GroupControlDisposition);
 
        void set_mute_points (MuteMaster::MutePoint);
        MuteMaster::MutePoint mute_points () const;
 
        bool muted () const;
-       void set_mute (bool yn, void* src);
+       void set_mute (bool yn, PBD::Controllable::GroupControlDisposition);
 
        bool muted_by_others() const;
 
        /* controls use set_solo() to modify this route's solo state
         */
 
-       void set_solo (bool yn, void *src, bool group_override = false);
+       void set_solo (bool yn, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
        bool soloed () const { return self_soloed () || soloed_by_others (); }
        void clear_all_solo_state ();
 
@@ -167,13 +167,13 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        bool soloed_by_others_downstream () const { return _soloed_by_others_downstream; }
        bool self_soloed () const { return _self_solo; }
 
-       void set_solo_isolated (bool yn, void *src);
+       void set_solo_isolated (bool yn, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
        bool solo_isolated() const;
 
-       void set_solo_safe (bool yn, void *src);
+       void set_solo_safe (bool yn, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
        bool solo_safe() const;
 
-       void set_listen (bool yn, void* src, bool group_override = false);
+       void set_listen (bool yn, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
        bool listening_via_monitor () const;
        void enable_monitor_send ();
 
@@ -286,12 +286,12 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        PBD::Signal0<void>       active_changed;
        PBD::Signal0<void>       phase_invert_changed;
        PBD::Signal0<void>       denormal_protection_changed;
-       PBD::Signal2<void,void*,bool> listen_changed;
-       PBD::Signal3<void,bool,void*,bool> solo_changed;
-       PBD::Signal1<void,void*> solo_safe_changed;
-       PBD::Signal1<void,void*> solo_isolated_changed;
-       PBD::Signal1<void,void*> comment_changed;
-       PBD::Signal1<void,void*> mute_changed;
+       PBD::Signal1<void,PBD::Controllable::GroupControlDisposition>  listen_changed;
+       PBD::Signal2<void,bool,PBD::Controllable::GroupControlDisposition>  solo_changed;
+       PBD::Signal0<void>       solo_safe_changed;
+       PBD::Signal0<void>       solo_isolated_changed;
+       PBD::Signal0<void>       comment_changed;
+       PBD::Signal0<void>       mute_changed;
        PBD::Signal0<void>       mute_points_changed;
 
        /** track numbers - assigned by session
@@ -438,6 +438,8 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
                void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
                void set_value_unchecked (double);
                double get_value () const;
+       private:
+               void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
        };
 
        struct MuteControllable : public RouteAutomationControl {
@@ -452,17 +454,20 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 
        private:
                boost::weak_ptr<Route> _route;
+               void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
        };
 
        class LIBARDOUR_API PhaseControllable : public RouteAutomationControl {
        public:
                PhaseControllable (std::string name, boost::shared_ptr<Route>);
                void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
+               /* currently no automation, so no need for set_value_unchecked() */
                void set_channel (uint32_t);
                double get_value () const;
                uint32_t channel() const;
        private:
                uint32_t _current_phase;
+               void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
        };
 
        void set_control (AutomationType, double val, PBD::Controllable::GroupControlDisposition group_override);
@@ -654,7 +659,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        bool           _solo_isolated;
        uint32_t       _solo_isolated_by_upstream;
 
-       void mod_solo_isolated_by_upstream (bool, void*);
+       void mod_solo_isolated_by_upstream (bool);
 
        bool           _denormal_protection;
 
index 763430e1f1c1d6a607ed4ebf5b747fb8c245759e..fc295a658cdb6c3dd844db50070748c5f049b664 100644 (file)
@@ -25,9 +25,9 @@
 #include <string>
 #include <stdint.h>
 
+#include "pbd/controllable.h"
 #include "pbd/signals.h"
 #include "pbd/stateful.h"
-#include "pbd/signals.h"
 
 #include "ardour/libardour_visibility.h"
 #include "ardour/types.h"
@@ -108,7 +108,7 @@ class LIBARDOUR_API RouteGroup : public SessionObject
 
        /* to use these, #include "ardour/route_group_specialized.h" */
 
-       template<class T> void apply (void (Track::*func)(T, void *), T val, void *src);
+       template<class T> void apply (void (Track::*func)(T, PBD::Controllable::GroupControlDisposition), T val, PBD::Controllable::GroupControlDisposition);
 
        /* fills at_set with all members of the group that are AudioTracks */
 
@@ -134,7 +134,7 @@ class LIBARDOUR_API RouteGroup : public SessionObject
 
        int set_state (const XMLNode&, int version);
 
-private:
+  private:
        boost::shared_ptr<RouteList> routes;
        boost::shared_ptr<Route> subgroup_bus;
 
index b0368cb2409d2fb725fb7c40d277fad4423b0816..0bf41667458c7f9ee236a05c64fa513b43600612 100644 (file)
@@ -20,6 +20,7 @@
 #ifndef __libardour_route_group_member_h__
 #define __libardour_route_group_member_h__
 
+#include "pbd/controllable.h"
 #include "pbd/signals.h"
 
 namespace ARDOUR  {
@@ -37,6 +38,8 @@ class LIBARDOUR_API RouteGroupMember
        /** Emitted when this member joins or leaves a route group */
        PBD::Signal0<void> route_group_changed;
 
+       bool use_group (PBD::Controllable::GroupControlDisposition gcd, bool (RouteGroup::*predicate)(void) const) const;
+
   protected:
        RouteGroup* _route_group;
 
index 242a16c43e471ecc0d72548886d99d552ac72256..800ddc4289d22630cf3d07a5121661f1ffed9cf4 100644 (file)
 namespace ARDOUR {
 
 template<class T> void
-RouteGroup::apply (void (Track::*func)(T, void *), T val, void* /*src*/)
+RouteGroup::apply (void (Track::*func)(T, PBD::Controllable::GroupControlDisposition), T val, PBD::Controllable::GroupControlDisposition group_override)
 {
        for (RouteList::iterator i = routes->begin(); i != routes->end(); i++) {
                boost::shared_ptr<Track> at;
 
                if ((at = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
-                       (at.get()->*func)(val, this);
+                       (at.get()->*func)(val, group_override);
                }
        }
 }
index 43bd7483fbb9ca77187da56fba00f682f000dc14..e28ff8e9661a720082ce8e03f857a8f6313a7d70 100644 (file)
@@ -739,16 +739,16 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        static const SessionEvent::RTeventCallback rt_cleanup;
 
-       void set_solo (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
+       void set_solo (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
        void clear_all_solo_state (boost::shared_ptr<RouteList>);
        void set_just_one_solo (boost::shared_ptr<Route>, bool, SessionEvent::RTeventCallback after = rt_cleanup);
-       void set_mute (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
-       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_record_safe (boost::shared_ptr<RouteList>, bool yn, 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_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);
+       void set_mute (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+       void set_listen (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+       void set_record_enabled (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+       void set_record_safe (boost::shared_ptr<RouteList>, bool yn, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+       void set_solo_isolated (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+       void set_monitoring (boost::shared_ptr<RouteList>, MonitorChoice, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+       void set_exclusive_input_active (boost::shared_ptr<RouteList> rt, bool onoff, bool flip_others = false);
 
        PBD::Signal1<void,bool> SoloActive;
        PBD::Signal0<void> SoloChanged;
@@ -1544,10 +1544,10 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        /* mixer stuff */
 
-       void route_listen_changed (bool group_override, boost::weak_ptr<Route>);
-       void route_mute_changed (void *src);
-       void route_solo_changed (bool self_solo_change, bool group_override, boost::weak_ptr<Route>);
-       void route_solo_isolated_changed (void *src, boost::weak_ptr<Route>);
+       void route_listen_changed (PBD::Controllable::GroupControlDisposition, boost::weak_ptr<Route>);
+       void route_mute_changed ();
+       void route_solo_changed (bool self_solo_change, PBD::Controllable::GroupControlDisposition group_override, boost::weak_ptr<Route>);
+       void route_solo_isolated_changed (boost::weak_ptr<Route>);
        void update_route_solo_state (boost::shared_ptr<RouteList> r = boost::shared_ptr<RouteList>());
 
        void listen_position_changed ();
@@ -1772,8 +1772,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        /* realtime "apply to set of routes" operations */
        template<typename T> SessionEvent*
-               get_rt_event (boost::shared_ptr<RouteList> rl, T targ, SessionEvent::RTeventCallback after, bool group_override,
-                             void (Session::*method) (boost::shared_ptr<RouteList>, T, bool)) {
+               get_rt_event (boost::shared_ptr<RouteList> rl, T targ, SessionEvent::RTeventCallback after, PBD::Controllable::GroupControlDisposition group_override,
+                             void (Session::*method) (boost::shared_ptr<RouteList>, T, PBD::Controllable::GroupControlDisposition)) {
                SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
                ev->rt_slot = boost::bind (method, this, rl, targ, group_override);
                ev->rt_return = after;
@@ -1782,15 +1782,15 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
                return ev;
        }
 
-       void rt_set_solo (boost::shared_ptr<RouteList>, bool yn, bool group_override);
-       void rt_clear_all_solo_state (boost::shared_ptr<RouteList>, bool yn, bool group_override);
-       void rt_set_just_one_solo (boost::shared_ptr<RouteList>, bool yn, bool /* ignored*/ );
-       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_record_enabled (boost::shared_ptr<RouteList>, bool yn, bool group_override);
-       void rt_set_record_safe (boost::shared_ptr<RouteList>, bool yn, bool group_override);
-       void rt_set_monitoring (boost::shared_ptr<RouteList>, MonitorChoice, bool group_override);
+       void rt_set_solo (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+       void rt_clear_all_solo_state (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+       void rt_set_just_one_solo (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition  /* ignored*/ );
+       void rt_set_mute (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+       void rt_set_listen (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+       void rt_set_solo_isolated (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+       void rt_set_record_enabled (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+       void rt_set_record_safe (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+       void rt_set_monitoring (boost::shared_ptr<RouteList>, MonitorChoice, PBD::Controllable::GroupControlDisposition group_override);
 
        /** temporary list of Diskstreams used only during load of 2.X sessions */
        std::list<boost::shared_ptr<Diskstream> > _diskstreams_2X;
index 5bf887f51728f97b2a3609e46710c12404268494..39f9a52ec5fc28348d03177ce983e7b258bd367f 100644 (file)
@@ -108,9 +108,9 @@ class LIBARDOUR_API Track : public Route, public PublicDiskstream
 
        bool record_enabled() const;
        bool record_safe () const;
-       void set_record_enabled (bool yn, void *src);
-       void set_record_safe (bool yn, void *src);
-       void prep_record_enabled (bool yn, void *src);
+       void set_record_enabled (bool yn, PBD::Controllable::GroupControlDisposition);
+       void set_record_safe (bool yn, PBD::Controllable::GroupControlDisposition);
+       void prep_record_enabled (bool yn, PBD::Controllable::GroupControlDisposition);
 
        bool using_diskstream_id (PBD::ID) const;
 
@@ -203,7 +203,8 @@ class LIBARDOUR_API Track : public Route, public PublicDiskstream
                FreezeState                        state;
        };
 
-       struct RecEnableControl : public AutomationControl {
+       class RecEnableControl : public AutomationControl {
+       public:
                RecEnableControl (boost::shared_ptr<Track> t);
 
                void set_value (double, PBD::Controllable::GroupControlDisposition);
@@ -211,6 +212,9 @@ class LIBARDOUR_API Track : public Route, public PublicDiskstream
                double get_value (void) const;
 
                boost::weak_ptr<Track> track;
+
+       private:
+               void _set_value (double, PBD::Controllable::GroupControlDisposition);
        };
 
        virtual void set_state_part_two () = 0;
index 9314e1270eed102a920ba8398739ae1e8760d370..867edaf5a39d5ef3e666d61565d1505304bba610 100644 (file)
@@ -37,17 +37,24 @@ GainControl::GainControl (Session& session, const Evoral::Parameter &param, boos
 }
 
 void
-GainControl::set_value (double val, PBD::Controllable::GroupControlDisposition /* group_override */)
+GainControl::set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
 {
        if (writable()) {
-               set_value_unchecked (val);
+               _set_value (val, group_override);
        }
 }
 
 void
 GainControl::set_value_unchecked (double val)
 {
-       AutomationControl::set_value (std::max (std::min (val, (double)_desc.upper), (double)_desc.lower), Controllable::NoGroup);
+       /* used only automation playback */
+       _set_value (val, Controllable::NoGroup);
+}
+
+void
+GainControl::_set_value (double val, Controllable::GroupControlDisposition group_override)
+{
+       AutomationControl::set_value (std::max (std::min (val, (double)_desc.upper), (double)_desc.lower), group_override);
        _session.set_dirty ();
 }
 
index 69d10c44e0cfe056d76188d1f02da8a8e961e50a..d3653dc929d279422422bde635660f9d6ce2b7af 100644 (file)
@@ -103,23 +103,23 @@ MidiTrack::create_diskstream ()
 
 
 void
-MidiTrack::set_record_enabled (bool yn, void *src)
+MidiTrack::set_record_enabled (bool yn, Controllable::GroupControlDisposition group_override)
 {
        if (_step_editing) {
                return;
        }
 
-       Track::set_record_enabled (yn, src);
+       Track::set_record_enabled (yn, group_override);
 }
 
 void
-MidiTrack::set_record_safe (bool yn, void *src)
+MidiTrack::set_record_safe (bool yn, Controllable::GroupControlDisposition group_override)
 {
        if (_step_editing) { /* REQUIRES REVIEW */
                return;
        }
 
-       Track::set_record_safe (yn, src);
+       Track::set_record_safe (yn, group_override);
 }
 
 void
@@ -725,15 +725,22 @@ MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState st
 }
 
 void
-MidiTrack::MidiControl::set_value (double val, PBD::Controllable::GroupControlDisposition /* group_override */)
+MidiTrack::MidiControl::set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
 {
        if (writable()) {
-               set_value_unchecked (val);
+               _set_value (val, group_override);
        }
 }
 
 void
-MidiTrack::MidiControl::set_value_unchecked(double val)
+MidiTrack::MidiControl::set_value_unchecked (double val)
+{
+       /* used only by automation playback */
+       _set_value (val, Controllable::NoGroup);
+}
+
+void
+MidiTrack::MidiControl::_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
 {
        const Evoral::Parameter &parameter = _list ? _list->parameter() : Control::parameter();
        const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
@@ -790,7 +797,7 @@ MidiTrack::MidiControl::set_value_unchecked(double val)
                _route->write_immediate_event(size,  ev);
        }
 
-       AutomationControl::set_value(val, Controllable::NoGroup);
+       AutomationControl::set_value(val, group_override);
 }
 
 void
index faf04cc8d7df0e7d989253268780a24679efa68f..a6a96787a28e4bf3904b1e8c503f18acc668fd83 100644 (file)
@@ -35,21 +35,27 @@ PanControllable::lower () const
 }
 
 void
-PanControllable::set_value (double v, PBD::Controllable::GroupControlDisposition /* group_override */)
+PanControllable::set_value (double v, PBD::Controllable::GroupControlDisposition group_override)
 {
        if (writable()) {
-               set_value_unchecked (v);
+               _set_value (v, group_override);
        }
 }
-
 void
 PanControllable::set_value_unchecked (double v)
+{
+       /* used only automation playback */
+       _set_value (v, Controllable::NoGroup);
+}
+
+void
+PanControllable::_set_value (double v, Controllable::GroupControlDisposition group_override)
 {
        boost::shared_ptr<Panner> p = owner->panner();
 
         if (!p) {
                 /* no panner: just do it */
-               AutomationControl::set_value (v, Controllable::NoGroup);
+               AutomationControl::set_value (v, group_override);
                 return;
         }
 
@@ -70,7 +76,7 @@ PanControllable::set_value_unchecked (double v)
         }
 
         if (can_set) {
-               AutomationControl::set_value (v, Controllable::NoGroup);
+               AutomationControl::set_value (v, group_override);
         }
 }
 
index 02b802e9559a52ad72cd3cfc43d7f16c7013970d..b001895e0e7ba86d337d54913472875dedd56261 100644 (file)
@@ -1349,15 +1349,21 @@ PluginInsert::PluginControl::PluginControl (PluginInsert*                     p,
 
 /** @param val `user' value */
 void
-PluginInsert::PluginControl::set_value (double user_val, PBD::Controllable::GroupControlDisposition /* group_override */)
+PluginInsert::PluginControl::set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
 {
        if (writable()) {
-               set_value_unchecked (user_val);
+               _set_value (user_val, group_override);
        }
 }
-
 void
 PluginInsert::PluginControl::set_value_unchecked (double user_val)
+{
+       /* used only by automation playback */
+       _set_value (user_val, Controllable::NoGroup);
+}
+
+void
+PluginInsert::PluginControl::_set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
 {
        /* FIXME: probably should be taking out some lock here.. */
 
@@ -1370,7 +1376,7 @@ PluginInsert::PluginControl::set_value_unchecked (double user_val)
                iasp->set_parameter (_list->parameter().id(), user_val);
        }
 
-       AutomationControl::set_value (user_val, Controllable::NoGroup);
+       AutomationControl::set_value (user_val, group_override);
 }
 
 void
index c07612f125cce183404030c299dd1f89ecbeb2d9..74fe71cfff96d39a063bd15737744c8a07f5ba5b 100644 (file)
@@ -406,7 +406,7 @@ Route::inc_gain (gain_t factor)
 void
 Route::set_gain (gain_t val, Controllable::GroupControlDisposition group_override)
 {
-       if (_route_group && (group_override != Controllable::NoGroup) && _route_group->is_active() && _route_group->is_gain()) {
+       if (use_group (group_override, &RouteGroup::is_gain)) {
 
                if (_route_group->is_relative()) {
 
@@ -459,7 +459,7 @@ Route::set_gain (gain_t val, Controllable::GroupControlDisposition group_overrid
 }
 
 void
-Route::set_trim (gain_t val, void * /* src */)
+Route::set_trim (gain_t val, Controllable::GroupControlDisposition /* group override */)
 {
        // TODO route group, see set_gain()
        _trim_control->route_set_value (val);
@@ -784,19 +784,14 @@ Route::passthru_silence (framepos_t start_frame, framepos_t end_frame, pframes_t
 }
 
 void
-Route::set_listen (bool yn, void* src, bool group_override)
+Route::set_listen (bool yn, Controllable::GroupControlDisposition group_override)
 {
        if (_solo_safe) {
                return;
        }
 
-       bool group_active = _route_group && _route_group->is_active() && _route_group->is_solo();
-       if (group_override && _route_group) {
-               group_active = !group_active;
-       }
-
-       if (_route_group && src != _route_group && group_active) {
-               _route_group->foreach_route (boost::bind (&Route::set_listen, _1, yn, _route_group, group_override));
+       if (use_group (group_override, &RouteGroup::is_solo)) {
+               _route_group->foreach_route (boost::bind (&Route::set_listen, _1, yn, Controllable::NoGroup));
                return;
        }
 
@@ -811,7 +806,7 @@ Route::set_listen (bool yn, void* src, bool group_override)
                        }
                        _mute_master->set_soloed_by_others (false);
 
-                       listen_changed (src, group_override); /* EMIT SIGNAL */
+                       listen_changed (group_override); /* EMIT SIGNAL */
                }
        }
 }
@@ -827,11 +822,11 @@ Route::listening_via_monitor () const
 }
 
 void
-Route::set_solo_safe (bool yn, void *src)
+Route::set_solo_safe (bool yn, Controllable::GroupControlDisposition /* group_override */)
 {
        if (_solo_safe != yn) {
                _solo_safe = yn;
-               solo_safe_changed (src);
+               solo_safe_changed ();
        }
 }
 
@@ -868,17 +863,17 @@ Route::clear_all_solo_state ()
 
        {
                PBD::Unwinder<bool> uw (_solo_safe, false);
-               set_solo (false, this);
+               set_solo (false, Controllable::NoGroup);
        }
 
        if (emit_changed) {
                set_mute_master_solo ();
-               solo_changed (false, this, false); /* EMIT SIGNAL */
+               solo_changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
        }
 }
 
 void
-Route::set_solo (bool yn, void *src, bool group_override)
+Route::set_solo (bool yn, Controllable::GroupControlDisposition group_override)
 {
        if (_solo_safe) {
                DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 ignore solo change due to solo-safe\n", name()));
@@ -890,21 +885,17 @@ Route::set_solo (bool yn, void *src, bool group_override)
                return;
        }
 
-       bool group_active = _route_group && _route_group->is_active() && _route_group->is_solo();
-       if (group_override && _route_group) {
-               group_active = !group_active;
-       }
-       if (_route_group && src != _route_group && group_active) {
-               _route_group->foreach_route (boost::bind (&Route::set_solo, _1, yn, _route_group, group_override));
+       if (use_group (group_override, &RouteGroup::is_solo)) {
+               _route_group->foreach_route (boost::bind (&Route::set_solo, _1, yn, Controllable::NoGroup));
                return;
        }
 
-       DEBUG_TRACE (DEBUG::Solo, string_compose ("%1: set solo => %2, src: %3 grp ? %4 currently self-soloed ? %5\n",
-                                                 name(), yn, src, (src == _route_group), self_soloed()));
+       DEBUG_TRACE (DEBUG::Solo, string_compose ("%1: set solo => %2, grp ? %3 currently self-soloed ? %4\n",
+                                                 name(), yn, enum_2_string(group_override), self_soloed()));
 
        if (self_soloed() != yn) {
                set_self_solo (yn);
-               solo_changed (true, src, group_override); /* EMIT SIGNAL */
+               solo_changed (true, group_override); /* EMIT SIGNAL */
                _solo_control->Changed (); /* EMIT SIGNAL */
        }
 
@@ -915,7 +906,7 @@ Route::set_solo (bool yn, void *src, bool group_override)
        */
 
        if (yn && Profile->get_trx()) {
-               set_mute (false, src);
+               set_mute (false, Controllable::UseGroup);
        }
 }
 
@@ -982,7 +973,7 @@ Route::mod_solo_by_others_upstream (int32_t delta)
        }
 
        set_mute_master_solo ();
-       solo_changed (false, this, false); /* EMIT SIGNAL */
+       solo_changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
 }
 
 void
@@ -1004,7 +995,7 @@ Route::mod_solo_by_others_downstream (int32_t delta)
        DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 SbD delta %2 = %3\n", name(), delta, _soloed_by_others_downstream));
 
        set_mute_master_solo ();
-       solo_changed (false, this, false); /* EMIT SIGNAL */
+       solo_changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
 }
 
 void
@@ -1015,7 +1006,7 @@ Route::set_mute_master_solo ()
 }
 
 void
-Route::mod_solo_isolated_by_upstream (bool yn, void* src)
+Route::mod_solo_isolated_by_upstream (bool yn)
 {
        bool old = solo_isolated ();
        DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 mod_solo_isolated_by_upstream cur: %2 d: %3\n",
@@ -1034,19 +1025,19 @@ Route::mod_solo_isolated_by_upstream (bool yn, void* src)
        if (solo_isolated() != old) {
                /* solo isolated status changed */
                _mute_master->set_solo_ignore (solo_isolated());
-               solo_isolated_changed (src); /* EMIT SIGNAL */
+               solo_isolated_changed (); /* EMIT SIGNAL */
        }
 }
 
 void
-Route::set_solo_isolated (bool yn, void *src)
+Route::set_solo_isolated (bool yn, Controllable::GroupControlDisposition group_override)
 {
        if (is_master() || is_monitor() || is_auditioner()) {
                return;
        }
 
-       if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_solo()) {
-               _route_group->foreach_route (boost::bind (&Route::set_solo_isolated, _1, yn, _route_group));
+       if (use_group (group_override, &RouteGroup::is_solo)) {
+               _route_group->foreach_route (boost::bind (&Route::set_solo_isolated, _1, yn, Controllable::NoGroup));
                return;
        }
 
@@ -1084,13 +1075,13 @@ Route::set_solo_isolated (bool yn, void *src)
                bool does_feed = feeds (*i, &sends_only);
 
                if (does_feed && !sends_only) {
-                       (*i)->mod_solo_isolated_by_upstream (yn, src);
+                       (*i)->mod_solo_isolated_by_upstream (yn);
                }
        }
 
        /* XXX should we back-propagate as well? (April 2010: myself and chris goddard think not) */
 
-       solo_isolated_changed (src); /* EMIT SIGNAL */
+       solo_isolated_changed (); /* EMIT SIGNAL */
 }
 
 bool
@@ -1106,16 +1097,16 @@ Route::set_mute_points (MuteMaster::MutePoint mp)
        mute_points_changed (); /* EMIT SIGNAL */
 
        if (_mute_master->muted_by_self()) {
-               mute_changed (this); /* EMIT SIGNAL */
+               mute_changed (); /* EMIT SIGNAL */
                _mute_control->Changed (); /* EMIT SIGNAL */
        }
 }
 
 void
-Route::set_mute (bool yn, void *src)
+Route::set_mute (bool yn, Controllable::GroupControlDisposition group_override)
 {
-       if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_mute()) {
-               _route_group->foreach_route (boost::bind (&Route::set_mute, _1, yn, _route_group));
+       if (use_group (group_override, &RouteGroup::is_mute)) {
+               _route_group->foreach_route (boost::bind (&Route::set_mute, _1, yn, Controllable::NoGroup));
                return;
        }
 
@@ -1126,7 +1117,7 @@ Route::set_mute (bool yn, void *src)
                */
                act_on_mute ();
                /* tell everyone else */
-               mute_changed (src); /* EMIT SIGNAL */
+               mute_changed (); /* EMIT SIGNAL */
                _mute_control->Changed (); /* EMIT SIGNAL */
        }
 }
@@ -2514,11 +2505,11 @@ Route::set_state (const XMLNode& node, int version)
        }
 
        if ((prop = node.property ("solo-isolated")) != 0) {
-               set_solo_isolated (string_is_affirmative (prop->value()), this);
+               set_solo_isolated (string_is_affirmative (prop->value()), Controllable::NoGroup);
        }
 
        if ((prop = node.property ("solo-safe")) != 0) {
-               set_solo_safe (string_is_affirmative (prop->value()), this);
+               set_solo_safe (string_is_affirmative (prop->value()), Controllable::NoGroup);
        }
 
        if ((prop = node.property (X_("phase-invert"))) != 0) {
@@ -2673,7 +2664,7 @@ Route::set_state_2X (const XMLNode& node, int version)
 
                /* XXX force reset of solo status */
 
-               set_solo (yn, this);
+               set_solo (yn);
        }
 
        if ((prop = node.property (X_("muted"))) != 0) {
@@ -3240,7 +3231,7 @@ void
 Route::set_comment (string cmt, void *src)
 {
        _comment = cmt;
-       comment_changed (src);
+       comment_changed ();
        _session.set_dirty ();
 }
 
@@ -3414,7 +3405,7 @@ Route::input_change_handler (IOChange change, void * /*src*/)
                if (_solo_isolated_by_upstream) {
                        // solo-isolate currently only propagates downstream
                        if (idelta < 0) {
-                               mod_solo_isolated_by_upstream (false, this);
+                               mod_solo_isolated_by_upstream (false);
                        }
                        // TODO think: mod_solo_isolated_by_upstream() does not take delta arg,
                        // but idelta can't be smaller than -1, can it?
@@ -3434,7 +3425,7 @@ Route::input_change_handler (IOChange change, void * /*src*/)
                        }
 
                        if (idelta < 0 && does_feed && !sends_only) {
-                               (*i)->mod_solo_isolated_by_upstream (false, this);
+                               (*i)->mod_solo_isolated_by_upstream (false);
                        }
                }
        }
@@ -3901,13 +3892,13 @@ Route::set_control (AutomationType type, double val, PBD::Controllable::GroupCon
        switch (type) {
        case GainAutomation:
                /* route must mediate group control */
-               set_gain (val, group_override); 
+               set_gain (val, group_override);
                return;
                break;
 
        case TrimAutomation:
                /* route must mediate group control */
-               set_trim (val, this); /* any "src" argument will do other than our route group */
+               set_trim (val, group_override); /* any "src" argument will do other than our route group */
                return;
                break;
 
@@ -3915,7 +3906,7 @@ Route::set_control (AutomationType type, double val, PBD::Controllable::GroupCon
                /* session must mediate group control */
                rl.reset (new RouteList);
                rl->push_back (shared_from_this());
-               _session.set_record_enabled (rl, val >= 0.5 ? true : false);
+               _session.set_record_enabled (rl, val >= 0.5 ? true : false, Session::rt_cleanup, group_override);
                return;
                break;
 
@@ -3924,7 +3915,7 @@ Route::set_control (AutomationType type, double val, PBD::Controllable::GroupCon
                rl.reset (new RouteList);
                rl->push_back (shared_from_this());
                if (Config->get_solo_control_is_listen_control()) {
-                       _session.set_listen (rl, val >= 0.5 ? true : false);
+                       _session.set_listen (rl, val >= 0.5 ? true : false, Session::rt_cleanup, group_override);
                } else {
                        _session.set_solo (rl, val >= 0.5 ? true : false);
                }
@@ -3936,7 +3927,7 @@ Route::set_control (AutomationType type, double val, PBD::Controllable::GroupCon
                /* session must mediate group control */
                rl.reset (new RouteList);
                rl->push_back (shared_from_this());
-               _session.set_mute (rl, !muted());
+               _session.set_mute (rl, !muted(), Session::rt_cleanup, group_override);
                return;
                break;
 
@@ -3976,15 +3967,15 @@ Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr<R
 }
 
 void
-Route::SoloControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /* group_override */)
+Route::SoloControllable::set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
 {
        if (writable()) {
-               set_value_unchecked (val);
+               _set_value (val, group_override);
        }
 }
 
 void
-Route::SoloControllable::set_value_unchecked (double val)
+Route::SoloControllable::_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
 {
        const bool bval = ((val >= 0.5) ? true : false);
 
@@ -3998,12 +3989,20 @@ Route::SoloControllable::set_value_unchecked (double val)
        rl->push_back (r);
 
        if (Config->get_solo_control_is_listen_control()) {
-               _session.set_listen (rl, bval);
+               _session.set_listen (rl, bval, Session::rt_cleanup, group_override);
        } else {
-               _session.set_solo (rl, bval);
+               _session.set_solo (rl, bval, Session::rt_cleanup, group_override);
        }
 }
 
+void
+Route::SoloControllable::set_value_unchecked (double val)
+{
+       /* Used only by automation playback */
+
+       _set_value (val, Controllable::NoGroup);
+}
+
 double
 Route::SoloControllable::get_value () const
 {
@@ -4053,15 +4052,22 @@ Route::MuteControllable::set_superficial_value(bool muted)
 }
 
 void
-Route::MuteControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /* group_override */)
+Route::MuteControllable::set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
 {
        if (writable()) {
-               set_value_unchecked (val);
+               _set_value (val, group_override);
        }
 }
 
 void
 Route::MuteControllable::set_value_unchecked (double val)
+{
+       /* used only automation playback */
+       _set_value (val, Controllable::NoGroup);
+}
+
+void
+Route::MuteControllable::_set_value (double val, Controllable::GroupControlDisposition group_override)
 {
        const bool bval = ((val >= 0.5) ? true : false);
 
@@ -4074,12 +4080,12 @@ Route::MuteControllable::set_value_unchecked (double val)
                // Set superficial/automation value to drive controller (and possibly record)
                set_superficial_value (bval);
                // Playing back automation, set route mute directly
-               r->set_mute (bval, this);
+               r->set_mute (bval, Controllable::NoGroup);
        } else {
                // Set from user, queue mute event
                boost::shared_ptr<RouteList> rl (new RouteList);
                rl->push_back (r);
-               _session.set_mute (rl, bval, Session::rt_cleanup);
+               _session.set_mute (rl, bval, Session::rt_cleanup, group_override);
        }
 }
 
index 3caa7cd1d0e8fc1db39639769ae4ddc8d4506e46..6ab2ade21e52cb712176dc87dc28b635bd111937 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "ardour/libardour_visibility.h"
 #include "ardour/route_group_member.h"
+#include "ardour/route_group.h"
 
 using namespace ARDOUR;
 
@@ -34,3 +35,12 @@ RouteGroupMember::set_route_group (RouteGroup *rg)
        _route_group = rg;
        route_group_changed (); /* EMIT SIGNAL */
 }
+
+bool
+RouteGroupMember::use_group (PBD::Controllable::GroupControlDisposition gcd, bool (RouteGroup::*predicate)(void) const) const
+{
+       return (gcd != PBD::Controllable::NoGroup) &&
+               (_route_group &&
+                ((gcd == PBD::Controllable::WholeGroup) ||
+                 (_route_group->is_active() && (_route_group->*predicate)())));
+}
index 8f71ef29ef07ef8041a36523a8c1788c90a51e17..70a62e5b751ae9e25cd913a2b8d9ba38262bfd74 100644 (file)
@@ -3281,10 +3281,10 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
                boost::weak_ptr<Route> wpr (*x);
                boost::shared_ptr<Route> r (*x);
 
-               r->listen_changed.connect_same_thread (*this, boost::bind (&Session::route_listen_changed, this, _2, wpr));
-               r->solo_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _3, wpr));
-               r->solo_isolated_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_isolated_changed, this, _1, wpr));
-               r->mute_changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this, _1));
+               r->listen_changed.connect_same_thread (*this, boost::bind (&Session::route_listen_changed, this, _1, wpr));
+               r->solo_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2, wpr));
+               r->solo_isolated_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_isolated_changed, this, wpr));
+               r->mute_changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this));
                r->output()->changed.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies_x, this, _1, _2));
                r->processors_changed.connect_same_thread (*this, boost::bind (&Session::route_processors_changed, this, _1));
 
@@ -3450,7 +3450,7 @@ Session::remove_routes (boost::shared_ptr<RouteList> routes_to_remove)
                                continue;
                        }
 
-                       (*iter)->set_solo (false, this);
+                       (*iter)->set_solo (false, Controllable::NoGroup);
 
                        rs->remove (*iter);
 
@@ -3558,13 +3558,13 @@ Session::remove_route (boost::shared_ptr<Route> route)
 }
 
 void
-Session::route_mute_changed (void* /*src*/)
+Session::route_mute_changed ()
 {
        set_dirty ();
 }
 
 void
-Session::route_listen_changed (bool group_override, boost::weak_ptr<Route> wpr)
+Session::route_listen_changed (Controllable::GroupControlDisposition group_override, boost::weak_ptr<Route> wpr)
 {
        boost::shared_ptr<Route> route = wpr.lock();
        if (!route) {
@@ -3575,18 +3575,32 @@ Session::route_listen_changed (bool group_override, boost::weak_ptr<Route> wpr)
        if (route->listening_via_monitor ()) {
 
                if (Config->get_exclusive_solo()) {
-                       /* new listen: disable all other listen, except solo-grouped channels */
+
                        RouteGroup* rg = route->route_group ();
-                       bool leave_group_alone = (rg && rg->is_active() && rg->is_solo());
-                       if (group_override && rg) {
-                               leave_group_alone = !leave_group_alone;
-                       }
+                       const bool group_already_accounted_for = route->use_group (group_override, &RouteGroup::is_solo);
+
                        boost::shared_ptr<RouteList> r = routes.reader ();
+
                        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner() || (leave_group_alone && ((*i)->route_group() == rg))) {
+                               if ((*i) == route) {
+                                       /* already changed */
+                                       continue;
+                               }
+
+                               if ((*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
+                                       /* route does not get solo propagated to it */
+                                       continue;
+                               }
+
+                               if ((group_already_accounted_for && (*i)->route_group() && (*i)->route_group() == rg)) {
+                                       /* this route is a part of the same solo group as the route
+                                        * that was changed. Changing that route did change or will
+                                        * change all group members appropriately, so we can ignore it
+                                        * here
+                                        */
                                        continue;
                                }
-                               (*i)->set_listen (false, this, group_override);
+                               (*i)->set_listen (false, Controllable::NoGroup);
                        }
                }
 
@@ -3600,7 +3614,7 @@ Session::route_listen_changed (bool group_override, boost::weak_ptr<Route> wpr)
        update_route_solo_state ();
 }
 void
-Session::route_solo_isolated_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
+Session::route_solo_isolated_changed (boost::weak_ptr<Route> wpr)
 {
        boost::shared_ptr<Route> route = wpr.lock ();
 
@@ -3630,7 +3644,7 @@ Session::route_solo_isolated_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
 }
 
 void
-Session::route_solo_changed (bool self_solo_change, bool group_override,  boost::weak_ptr<Route> wpr)
+Session::route_solo_changed (bool self_solo_change, Controllable::GroupControlDisposition group_override,  boost::weak_ptr<Route> wpr)
 {
        DEBUG_TRACE (DEBUG::Solo, string_compose ("route solo change, self = %1\n", self_solo_change));
 
@@ -3651,21 +3665,51 @@ Session::route_solo_changed (bool self_solo_change, bool group_override,  boost:
                delta = -1;
        }
 
+       /* the route may be a member of a group that has shared-solo
+        * semantics. If so, then all members of that group should follow the
+        * solo of the changed route. But ... this is optional, controlled by a
+        * Controllable::GroupControlDisposition.
+        *
+        * The first argument to the signal that this method is connected to is the
+        * GroupControlDisposition value that was used to change solo.
+        *
+        * If the solo change was done with group semantics (either WholeGroup
+        * (force the entire group to change even if the group shared solo is
+        * disabled) or UseGroup (use the group, which may or may not have the
+        * shared solo property enabled)) then as we propagate the change to
+        * the entire session we should IGNORE THE GROUP that the changed route
+        * belongs to.
+        */
+
        RouteGroup* rg = route->route_group ();
-       bool leave_group_alone = (rg && rg->is_active() && rg->is_solo());
-       if (group_override && rg) {
-               leave_group_alone = !leave_group_alone;
-       }
+       const bool group_already_accounted_for = route->use_group (group_override, &RouteGroup::is_solo);
+
        if (delta == 1 && Config->get_exclusive_solo()) {
 
                /* new solo: disable all other solos, but not the group if its solo-enabled */
 
                for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                       if ((*i) == route || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner() ||
-                           (leave_group_alone && ((*i)->route_group() == rg))) {
+
+                       if ((*i) == route) {
+                               /* already changed */
+                               continue;
+                       }
+
+                       if ((*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
+                               /* route does not get solo propagated to it */
+                               continue;
+                       }
+
+                       if ((group_already_accounted_for && (*i)->route_group() && (*i)->route_group() == rg)) {
+                               /* this route is a part of the same solo group as the route
+                                * that was changed. Changing that route did change or will
+                                * change all group members appropriately, so we can ignore it
+                                * here
+                                */
                                continue;
                        }
-                       (*i)->set_solo (false, this, group_override);
+
+                       (*i)->set_solo (false, group_override);
                }
        }
 
@@ -3679,8 +3723,22 @@ Session::route_solo_changed (bool self_solo_change, bool group_override,  boost:
                bool via_sends_only;
                bool in_signal_flow;
 
-               if ((*i) == route || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner() ||
-                   (leave_group_alone && ((*i)->route_group() == rg))) {
+               if ((*i) == route) {
+                       /* already changed */
+                       continue;
+               }
+
+               if ((*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
+                       /* route does not get solo propagated to it */
+                       continue;
+               }
+
+               if ((group_already_accounted_for && (*i)->route_group() && (*i)->route_group() == rg)) {
+                       /* this route is a part of the same solo group as the route
+                        * that was changed. Changing that route did change or will
+                        * change all group members appropriately, so we can ignore it
+                        * here
+                        */
                        continue;
                }
 
@@ -3746,7 +3804,7 @@ Session::route_solo_changed (bool self_solo_change, bool group_override,  boost:
        for (RouteList::iterator i = uninvolved.begin(); i != uninvolved.end(); ++i) {
                DEBUG_TRACE (DEBUG::Solo, string_compose ("mute change for %1, which neither feeds or is fed by %2\n", (*i)->name(), route->name()));
                (*i)->act_on_mute ();
-               (*i)->mute_changed (this);
+               (*i)->mute_changed ();
        }
 
        SoloChanged (); /* EMIT SIGNAL */
@@ -3777,7 +3835,7 @@ Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
                                listeners++;
                                something_listening = true;
                        } else {
-                               (*i)->set_listen (false, this);
+                               (*i)->set_listen (false, Controllable::NoGroup);
                        }
                }
 
index c7bced83463cd7ecee0a85ce64e430dabde6bd5c..baff2c7bfec9b5140de01d5727977b26f40e5b32 100644 (file)
@@ -350,7 +350,7 @@ Session::mmc_record_enable (MIDI::MachineControl &mmc, size_t trk, bool enabled)
 
                if ((at = dynamic_cast<AudioTrack*>((*i).get())) != 0) {
                        if (trk == at->remote_control_id()) {
-                               at->set_record_enabled (enabled, &mmc);
+                               at->set_record_enabled (enabled, Controllable::UseGroup);
                                break;
                        }
                }
index 2b24b59970175c4e581a3c38edf3ce85d1ae69ec..deb033c6fd72cb1db34853f21913232f8e18680b 100644 (file)
@@ -33,13 +33,15 @@ using namespace ARDOUR;
 using namespace Glib;
 
 void
-Session::set_monitoring (boost::shared_ptr<RouteList> rl, MonitorChoice mc, SessionEvent::RTeventCallback after, bool group_override)
+Session::set_monitoring (boost::shared_ptr<RouteList> rl, MonitorChoice mc, 
+                         SessionEvent::RTeventCallback after,
+                         Controllable::GroupControlDisposition group_override)
 {
        queue_event (get_rt_event (rl, mc, after, group_override, &Session::rt_set_monitoring));
 }
 
 void
-Session::rt_set_monitoring (boost::shared_ptr<RouteList> rl, MonitorChoice mc, bool /* group_override */)
+Session::rt_set_monitoring (boost::shared_ptr<RouteList> rl, MonitorChoice mc, Controllable::GroupControlDisposition /*group_override*/)
 {
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
                if (!(*i)->is_auditioner()) {
@@ -56,11 +58,11 @@ Session::rt_set_monitoring (boost::shared_ptr<RouteList> rl, MonitorChoice mc, b
 void
 Session::clear_all_solo_state (boost::shared_ptr<RouteList> rl)
 {
-       queue_event (get_rt_event (rl, false, rt_cleanup, false, &Session::rt_clear_all_solo_state));
+       queue_event (get_rt_event (rl, false, rt_cleanup, Controllable::NoGroup, &Session::rt_clear_all_solo_state));
 }
 
 void
-Session::rt_clear_all_solo_state (boost::shared_ptr<RouteList> rl, bool /* yn */, bool /* group_override */)
+Session::rt_clear_all_solo_state (boost::shared_ptr<RouteList> rl, bool /* yn */, Controllable::GroupControlDisposition /* group_override */)
 {
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
                if ((*i)->is_auditioner()) {
@@ -72,17 +74,18 @@ Session::rt_clear_all_solo_state (boost::shared_ptr<RouteList> rl, bool /* yn */
 }
 
 void
-Session::set_solo (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
+Session::set_solo (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after,
+                   Controllable::GroupControlDisposition group_override)
 {
        queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_solo));
 }
 
 void
-Session::rt_set_solo (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
+Session::rt_set_solo (boost::shared_ptr<RouteList> rl, bool yn, Controllable::GroupControlDisposition group_override)
 {
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
                if (!(*i)->is_auditioner()) {
-                       (*i)->set_solo (yn, this, group_override);
+                       (*i)->set_solo (yn, group_override);
                }
        }
 
@@ -104,38 +107,38 @@ Session::set_just_one_solo (boost::shared_ptr<Route> r, bool yn, SessionEvent::R
        boost::shared_ptr<RouteList> rl (new RouteList);
        rl->push_back (r);
 
-       queue_event (get_rt_event (rl, yn, after, false, &Session::rt_set_just_one_solo));
+       queue_event (get_rt_event (rl, yn, after, Controllable::NoGroup, &Session::rt_set_just_one_solo));
 }
 
 void
-Session::rt_set_just_one_solo (boost::shared_ptr<RouteList> just_one, bool yn, bool /*ignored*/)
+Session::rt_set_just_one_solo (boost::shared_ptr<RouteList> just_one, bool yn, Controllable::GroupControlDisposition /*ignored*/)
 {
        boost::shared_ptr<RouteList> rl = routes.reader ();
        boost::shared_ptr<Route> r = just_one->front();
 
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
                if (!(*i)->is_auditioner() && r != *i) {
-                       (*i)->set_solo (!yn, (*i)->route_group());
+                       (*i)->set_solo (!yn, Controllable::NoGroup);
                }
        }
 
-       r->set_solo (yn, r->route_group());
+       r->set_solo (yn, Controllable::NoGroup);
 
        set_dirty();
 }
 
 void
-Session::set_listen (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
+Session::set_listen (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, Controllable::GroupControlDisposition group_override)
 {
        queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_listen));
 }
 
 void
-Session::rt_set_listen (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
+Session::rt_set_listen (boost::shared_ptr<RouteList> rl, bool yn, Controllable::GroupControlDisposition group_override)
 {
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
                if (!(*i)->is_auditioner()) {
-                       (*i)->set_listen (yn, this, group_override);
+                       (*i)->set_listen (yn, group_override);
                }
        }
 
@@ -143,7 +146,7 @@ Session::rt_set_listen (boost::shared_ptr<RouteList> rl, bool yn, bool group_ove
 }
 
 void
-Session::set_mute (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
+Session::set_mute (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, Controllable::GroupControlDisposition group_override)
 {
        /* Set superficial value of mute controls for automation. */
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
@@ -155,11 +158,11 @@ Session::set_mute (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeve
 }
 
 void
-Session::rt_set_mute (boost::shared_ptr<RouteList> rl, bool yn, bool /*group_override*/)
+Session::rt_set_mute (boost::shared_ptr<RouteList> rl, bool yn, Controllable::GroupControlDisposition group_override)
 {
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
                if (!(*i)->is_monitor() && !(*i)->is_auditioner()) {
-                       (*i)->set_mute (yn, this);
+                       (*i)->set_mute (yn, group_override);
                }
        }
 
@@ -167,17 +170,17 @@ Session::rt_set_mute (boost::shared_ptr<RouteList> rl, bool yn, bool /*group_ove
 }
 
 void
-Session::set_solo_isolated (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
+Session::set_solo_isolated (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, Controllable::GroupControlDisposition group_override)
 {
        queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_solo_isolated));
 }
 
 void
-Session::rt_set_solo_isolated (boost::shared_ptr<RouteList> rl, bool yn, bool /*group_override*/)
+Session::rt_set_solo_isolated (boost::shared_ptr<RouteList> rl, bool yn, Controllable::GroupControlDisposition 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 (yn, this);
+                       (*i)->set_solo_isolated (yn, group_override);
                }
        }
 
@@ -185,7 +188,7 @@ Session::rt_set_solo_isolated (boost::shared_ptr<RouteList> rl, bool yn, bool /*
 }
 
 void
-Session::set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
+Session::set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, Controllable::GroupControlDisposition group_override)
 {
        if (!writable()) {
                return;
@@ -206,7 +209,7 @@ Session::set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, SessionEv
                boost::shared_ptr<Track> t;
 
                if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
-                       t->prep_record_enabled (yn, (group_override ? (void*) t->route_group() : (void *) this));
+                       t->prep_record_enabled (yn, group_override);
                }
        }
 
@@ -214,7 +217,7 @@ Session::set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, SessionEv
 }
 
 void
-Session::rt_set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
+Session::rt_set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, Controllable::GroupControlDisposition group_override)
 {
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
                if ((*i)->is_auditioner() || (*i)->record_safe ()) {
@@ -224,7 +227,7 @@ Session::rt_set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, bool g
                boost::shared_ptr<Track> t;
 
                if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
-                       t->set_record_enabled (yn, (group_override ? (void*) t->route_group() : (void *) this));
+                       t->set_record_enabled (yn, group_override);
                }
        }
 
@@ -233,14 +236,14 @@ Session::rt_set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, bool g
 
 
 void
-Session::set_record_safe (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
+Session::set_record_safe (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, Controllable::GroupControlDisposition group_override)
 {
        set_record_enabled (rl, false, after, group_override);
        queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_record_safe));
 }
 
 void
-Session::rt_set_record_safe (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
+Session::rt_set_record_safe (boost::shared_ptr<RouteList> rl, bool yn, Controllable::GroupControlDisposition group_override)
 {
        for (RouteList::iterator i = rl->begin (); i != rl->end (); ++i) {
                if ((*i)->is_auditioner ()) { // REQUIRES REVIEW Can audiotioner be in Record Safe mode?
@@ -250,7 +253,7 @@ Session::rt_set_record_safe (boost::shared_ptr<RouteList> rl, bool yn, bool grou
                boost::shared_ptr<Track> t;
 
                if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
-                       t->set_record_safe (yn, (group_override ? (void*) t->route_group () : (void *) this));
+                       t->set_record_safe (yn, group_override);
                }
        }
 
index 21256b09ce9c80edfa2b98321721cecf95b80b30..63c347770445198a724911f362c49a618c4941a4 100644 (file)
@@ -190,22 +190,30 @@ Track::RecEnableControl::RecEnableControl (boost::shared_ptr<Track> t)
 }
 
 void
-Track::RecEnableControl::set_value (double val, Controllable::GroupControlDisposition /* group_override */)
+Track::RecEnableControl::set_value (double val, Controllable::GroupControlDisposition group_override)
 {
        if (writable()) {
-               set_value_unchecked (val);
+               _set_value (val, group_override);
        }
 }
 
 void
 Track::RecEnableControl::set_value_unchecked (double val)
+{
+       if (writable()) {
+               _set_value (val, Controllable::NoGroup);
+       }
+}
+
+void
+Track::RecEnableControl::_set_value (double val, Controllable::GroupControlDisposition group_override)
 {
        boost::shared_ptr<Track> t = track.lock ();
        if (!t) {
                return;
        }
 
-       t->set_record_enabled (val >= 0.5 ? true : false, this);
+       t->set_record_enabled (val >= 0.5 ? true : false, group_override);
 }
 
 double
@@ -238,7 +246,7 @@ Track::can_record()
 }
 
 void
-Track::prep_record_enabled (bool yn, void *src)
+Track::prep_record_enabled (bool yn, Controllable::GroupControlDisposition group_override)
 {
        if (yn && record_safe ()) {
            return;
@@ -252,8 +260,8 @@ Track::prep_record_enabled (bool yn, void *src)
                return;
        }
 
-       if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_recenable()) {
-               _route_group->apply (&Track::prep_record_enabled, yn, _route_group);
+       if (use_group (group_override, &RouteGroup::is_recenable)) {
+               _route_group->apply (&Track::prep_record_enabled, yn, Controllable::NoGroup);
                return;
        }
 
@@ -282,7 +290,7 @@ Track::prep_record_enabled (bool yn, void *src)
 }
 
 void
-Track::set_record_enabled (bool yn, void *src)
+Track::set_record_enabled (bool yn, Controllable::GroupControlDisposition group_override)
 {
        if (_diskstream->record_safe ()) {
            return;
@@ -296,8 +304,8 @@ Track::set_record_enabled (bool yn, void *src)
                return;
        }
 
-       if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_recenable()) {
-               _route_group->apply (&Track::set_record_enabled, yn, _route_group);
+       if (use_group (group_override, &RouteGroup::is_recenable)) {
+               _route_group->apply (&Track::set_record_enabled, yn, Controllable::NoGroup);
                return;
        }
 
@@ -313,18 +321,18 @@ Track::record_safe () const
 }
 
 void
-Track::set_record_safe (bool yn, void *src)
+Track::set_record_safe (bool yn, Controllable::GroupControlDisposition group_override)
 {
-       if (!_session.writable()) { /* REQUIRES REVIEW */
+       if (!_session.writable()) {
                return;
        }
 
-       if (_freeze_record.state == Frozen) { /* REQUIRES REVIEW */
+       if (_freeze_record.state == Frozen) {
                return;
        }
 
-       if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_recenable()) {
-               _route_group->apply (&Track::set_record_safe, yn, _route_group);
+       if (use_group (group_override, &RouteGroup::is_recenable)) {
+               _route_group->apply (&Track::set_record_safe, yn, Controllable::NoGroup);
                return;
        }
 
@@ -1149,4 +1157,3 @@ Track::metering_state () const
        }
        return rv ? MeteringInput : MeteringRoute;
 }
-
index 1ce51bcd7552f7fdb1985e121f376e0762d633c3..6d016359bb3a15192e3afb14d62226c20c7732a5 100644 (file)
@@ -199,7 +199,7 @@ ControlProtocol::route_set_rec_enable (uint32_t table_index, bool yn)
        boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack>(r);
 
        if (at) {
-               at->set_record_enabled (yn, this);
+               at->set_record_enabled (yn, Controllable::NoGroup);
        }
 }
 
@@ -312,7 +312,7 @@ ControlProtocol::route_set_muted (uint32_t table_index, bool yn)
        boost::shared_ptr<Route> r = route_table[table_index];
 
        if (r != 0) {
-               r->set_mute (yn, this);
+               r->set_mute (yn, Controllable::UseGroup);
        }
 }
 
@@ -343,7 +343,7 @@ ControlProtocol::route_set_soloed (uint32_t table_index, bool yn)
        boost::shared_ptr<Route> r = route_table[table_index];
 
        if (r != 0) {
-               r->set_solo (yn, this);
+               r->set_solo (yn, Controllable::UseGroup);
        }
 }
 
index 50250a5f13ca2e30f7ea0a23ffae6ca7bc3a4bb5..a1ca393d7309cf8cbfc4b877f904ef04f7cf41f9 100644 (file)
@@ -1107,9 +1107,9 @@ FaderPort::set_current_route (boost::shared_ptr<Route> r)
        if (_current_route) {
                _current_route->DropReferences.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::drop_current_route, this), this);
 
-               _current_route->mute_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_mute, this, _1), this);
-               _current_route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_solo, this, _1, _2, _3), this);
-               _current_route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_listen, this, _1, _2), this);
+               _current_route->mute_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_mute, this), this);
+               _current_route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_solo, this), this);
+               _current_route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_listen, this), this);
 
                boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (_current_route);
                if (t) {
@@ -1187,7 +1187,7 @@ FaderPort::map_cut ()
 }
 
 void
-FaderPort::map_mute (void*)
+FaderPort::map_mute ()
 {
        if (_current_route) {
                if (_current_route->muted()) {
@@ -1204,7 +1204,7 @@ FaderPort::map_mute (void*)
 }
 
 void
-FaderPort::map_solo (bool, void*, bool)
+FaderPort::map_solo ()
 {
        if (_current_route) {
                get_button (Solo).set_led_state (_output_port, _current_route->soloed() || _current_route->listening_via_monitor());
@@ -1214,7 +1214,7 @@ FaderPort::map_solo (bool, void*, bool)
 }
 
 void
-FaderPort::map_listen (void*, bool)
+FaderPort::map_listen ()
 {
        if (_current_route) {
                get_button (Solo).set_led_state (_output_port, _current_route->listening_via_monitor());
@@ -1292,8 +1292,7 @@ FaderPort::map_route_state ()
                stop_blinking (Solo);
                get_button (Rec).set_led_state (_output_port, false);
        } else {
-               /* arguments to these map_*() methods are all ignored */
-               map_solo (false, 0, false);
+               map_solo ();
                map_recenable ();
                map_gain ();
                map_auto ();
@@ -1301,7 +1300,7 @@ FaderPort::map_route_state ()
                if (_current_route == session->monitor_out()) {
                        map_cut ();
                } else {
-                       map_mute (0);
+                       map_mute ();
                }
        }
 }
index 025cf09e0053efdf4ede3b62e2fa232732c0a8d4..d0a4d915f08c48bb2f2014318aabc5c5b42cf772 100644 (file)
@@ -302,9 +302,9 @@ class FaderPort : public ARDOUR::ControlProtocol, public AbstractUI<FaderPortReq
        PBD::ScopedConnectionList route_connections;
 
        void map_route_state ();
-       void map_solo (bool,void*,bool);
-       void map_listen (void*,bool);
-       void map_mute (void*);
+       void map_solo ();
+       void map_listen ();
+       void map_mute ();
        void map_recenable ();
        void map_gain ();
        void map_cut ();
index af938b89904177a07d7b24a58f4fb020d8b4de42..582f7e34bf8a1997d2ce721b5a15f2bb3e360254 100644 (file)
@@ -876,15 +876,7 @@ Strip::handle_button (Button& button, ButtonState bs)
                                DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
                                _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
 
-                               float new_value;
-                               int ms = _surface->mcp().main_modifier_state();
-
-                               if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
-                                       /* reset to default/normal value */
-                                       new_value = control->normal();
-                               } else {
-                                       new_value = control->get_value() ? 0.0 : 1.0;
-                               }
+                               float new_value = control->get_value() ? 0.0 : 1.0;
 
                                /* get all controls that either have their
                                 * button down or are within a range of
@@ -897,10 +889,18 @@ Strip::handle_button (Button& button, ButtonState bs)
                                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
                                                                            controls.size(), control->parameter().type(), new_value));
 
-                               /* apply change */
+                               /* apply change, with potential modifier semantics */
+
+                               Controllable::GroupControlDisposition gcd;
+
+                               if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
+                                       gcd = Controllable::NoGroup;
+                               } else {
+                                       gcd = Controllable::UseGroup;
+                               }
 
                                for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
-                                       (*c)->set_value (new_value, Controllable::NoGroup);
+                                       (*c)->set_value (new_value, gcd);
                                }
 
                        } else {
index 7504cf0cdbc41ec2fdd8829d096667a11294b007..7308941ac7c23957deb54f1c36de3885050ae0d8 100644 (file)
@@ -1047,7 +1047,7 @@ OSC::route_mute (int rid, int yn)
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
 
        if (r) {
-               r->set_mute (yn, this);
+               r->set_mute (yn, PBD::Controllable::NoGroup);
        }
 
        return 0;
@@ -1063,7 +1063,7 @@ OSC::route_solo (int rid, int yn)
        if (r) {
                boost::shared_ptr<RouteList> rl (new RouteList);
                rl->push_back (r);
-               session->set_solo (rl, yn);
+               session->set_solo (rl, yn, Session::rt_cleanup, PBD::Controllable::NoGroup);
        }
 
        return 0;
@@ -1077,7 +1077,7 @@ OSC::route_recenable (int rid, int yn)
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
 
        if (r) {
-               r->set_record_enabled (yn, this);
+               r->set_record_enabled (yn, PBD::Controllable::NoGroup);
        }
 
        return 0;
@@ -1112,7 +1112,7 @@ OSC::route_set_trim_abs (int rid, float level)
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
 
        if (r) {
-               r->set_trim (level, this);
+               r->set_trim (level, PBD::Controllable::NoGroup);
        }
 
        return 0;