Fix crash when re-assigning groups
authorRobin Gareus <robin@gareus.org>
Sun, 16 Sep 2018 21:08:41 +0000 (23:08 +0200)
committerRobin Gareus <robin@gareus.org>
Sun, 16 Sep 2018 21:08:41 +0000 (23:08 +0200)
This works around an issue where gtk sends two callbacks when a radio
selection changes. First: unselect, then select new item.

Previously:
 Two tracks, two groups. Select all tracks, assign to 2nd group. Crash.

The first callback, "unselect" iterates over all tracks, removes them
from any groups. Eventually all groups are unused and hence destroyed.

The 2nd callback - "select" - now uses a just destroyed group.

gtk2_ardour/route_group_menu.cc
gtk2_ardour/route_group_menu.h

index 5ccafaec398c70467c9313d65c8943ccd4449126..63577392a779ab5b39dd48c3eca61754d3db04e6 100644 (file)
@@ -88,7 +88,7 @@ RouteGroupMenu::build (WeakRouteList const & s)
        RadioMenuItem::Group group;
        items.push_back (RadioMenuElem (group, _("No Group")));
        RadioMenuItem* i = static_cast<RadioMenuItem *> (&items.back ());
-       i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::set_group), (RouteGroup *) 0));
+       i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::set_group), i, (RouteGroup *) 0));
 
        if (groups.size() == 1 && *groups.begin() == 0) {
                i->set_active ();
@@ -116,7 +116,7 @@ RouteGroupMenu::add_item (RouteGroup* rg, std::set<RouteGroup*> const & groups,
 
        items.push_back (RadioMenuElem (*group, rg->name()));
        RadioMenuItem* i = static_cast<RadioMenuItem*> (&items.back ());
-       i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::set_group), rg));
+       i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::set_group), i, rg));
 
        if (groups.size() == 1 && *groups.begin() == rg) {
                /* there's only one active group, and it's this one */
@@ -131,11 +131,14 @@ RouteGroupMenu::add_item (RouteGroup* rg, std::set<RouteGroup*> const & groups,
  *  @param Group, or 0 for none.
  */
 void
-RouteGroupMenu::set_group (RouteGroup* g)
+RouteGroupMenu::set_group (Gtk::RadioMenuItem* e, RouteGroup* g)
 {
        if (_inhibit_group_selected) {
                return;
        }
+       if (e && !e->get_active()) {
+               return;
+       }
 
        for (WeakRouteList::const_iterator i = _subject.begin(); i != _subject.end(); ++i) {
                boost::shared_ptr<Route> r = i->lock ();
@@ -173,7 +176,7 @@ RouteGroupMenu::new_group_dialog_finished (int r, RouteGroupDialog* d)
 {
        if (r == RESPONSE_OK) {
                _session->add_route_group (d->group());
-               set_group (d->group());
+               set_group (0, d->group());
        } else {
                delete d->group ();
        }
index 334a3b504e99b6ef7857bbecd4edc9aa7fcfad97..b29114a14501acc2c47f9996d7869a8e4630c6a7 100644 (file)
@@ -38,7 +38,7 @@ public:
   private:
        void add_item (ARDOUR::RouteGroup *, std::set<ARDOUR::RouteGroup*> const &, Gtk::RadioMenuItem::Group*);
        void new_group ();
-       void set_group (ARDOUR::RouteGroup *);
+       void set_group (Gtk::RadioMenuItem*, ARDOUR::RouteGroup *);
        void new_group_dialog_finished (int, RouteGroupDialog*);
 
        Gtk::Menu* _menu;