GroupTabs: use weak_ptr to manage RouteGroups

GroupTabs only get updated during ::render() (don't ask, don't tell),
and since there is no ::render() call during Session deletion, owning
a shared_ptr<RouteGroup> makes the RouteGroup outlive the session itself.
This commit is contained in:
Paul Davis 2025-12-16 20:19:11 -07:00
parent 4ad6ffec3d
commit 8b1b1e2362
5 changed files with 41 additions and 33 deletions

View file

@ -51,7 +51,6 @@ EditorGroupTabs::compute_tabs () const
Tab tab;
tab.from = 0;
tab.group = 0;
int32_t y = 0;
for (TrackViewList::iterator i = _editor.track_views.begin(); i != _editor.track_views.end(); ++i) {
@ -61,9 +60,10 @@ EditorGroupTabs::compute_tabs () const
}
std::shared_ptr<RouteGroup> g ((*i)->route_group ());
std::shared_ptr<RouteGroup> tab_group (tab.group.lock());
if (g != tab.group) {
if (tab.group) {
if (g != tab_group) {
if (tab_group) {
tab.to = y;
tabs.push_back (tab);
}
@ -78,7 +78,7 @@ EditorGroupTabs::compute_tabs () const
y += (*i)->effective_height ();
}
if (tab.group) {
if (tab.group.lock()) {
tab.to = y;
tabs.push_back (tab);
}
@ -99,9 +99,11 @@ EditorGroupTabs::draw_tab (cairo_t* cr, Tab const & tab)
double const arc_radius = get_width();
double r, g, b, a;
if (tab.group && tab.group->is_active()) {
std::shared_ptr<RouteGroup> tab_group (tab.group.lock());
if (tab_group && tab_group->is_active()) {
Gtkmm2ext::color_to_rgba (tab.color, r, g, b, a);
} else if (!tab.group && _dragging_new_tab) {
} else if (!tab_group && _dragging_new_tab) {
Gdk::Color col = ARDOUR_UI_UTILS::round_robin_palette_color (true);
color_t ct = Gtkmm2ext::gdk_color_to_rgba (col);
Gtkmm2ext::color_to_rgba (ct, r, g, b, a);
@ -119,14 +121,14 @@ EditorGroupTabs::draw_tab (cairo_t* cr, Tab const & tab)
cairo_line_to (cr, 0, from + arc_radius);
cairo_fill (cr);
if (tab.group && (to - from) > arc_radius) {
if (tab_group && (to - from) > arc_radius) {
int text_width, text_height;
Glib::RefPtr<Pango::Layout> layout;
layout = Pango::Layout::create (get_pango_context ());
layout->set_ellipsize (Pango::ELLIPSIZE_MIDDLE);
layout->set_text (tab.group->name ());
layout->set_text (tab_group->name ());
layout->set_width ((to - from - arc_radius) * PANGO_SCALE);
layout->get_pixel_size (text_width, text_height);
@ -210,4 +212,3 @@ EditorGroupTabs::selected_routes () const
return rl;
}

View file

@ -209,7 +209,7 @@ GroupTabs::on_button_press_event (GdkEventButton* ev)
} else if (ev->button == 3) {
std::shared_ptr<RouteGroup> g (t ? t->group : nullptr);
std::shared_ptr<RouteGroup> g (t ? t->group.lock() : nullptr);
if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier) && g) {
remove_group (g);
@ -265,13 +265,17 @@ GroupTabs::on_button_release_event (GdkEventButton*)
if (!_drag_moved) {
if (_dragging->group) {
std::shared_ptr<RouteGroup> group (_dragging->group.lock());
if (group) {
/* toggle active state */
_dragging->group->set_active (!_dragging->group->is_active (), this);
group->set_active (!group->is_active (), this);
}
} else {
/* finish drag */
std::shared_ptr<RouteGroup> group (_dragging->group.lock());
RouteList routes = routes_for_tab (_dragging);
if (!routes.empty()) {
@ -285,7 +289,7 @@ GroupTabs::on_button_release_event (GdkEventButton*)
*/
for (RouteList::const_iterator i = routes.begin(); i != routes.end(); ++i) {
/* RouteGroup::add () ignores routes already present in the set */
_dragging->group->add (*i);
group->add (*i);
}
for (auto const& i : *r) {
@ -295,7 +299,7 @@ GroupTabs::on_button_release_event (GdkEventButton*)
bool const now_in_tab = find (routes.begin(), routes.end(), i) != routes.end();
if (was_in_tab && !now_in_tab) {
_dragging->group->remove (i);
group->remove (i);
}
}

View file

@ -75,12 +75,12 @@ public:
protected:
struct Tab {
Tab () : group (0) {}
Tab () {}
double from;
double to;
uint32_t color; ///< color
std::shared_ptr<ARDOUR::RouteGroup> group; ///< route group
std::weak_ptr<ARDOUR::RouteGroup> group; ///< route group
};
/** @return Size of the widget along the primary axis */

View file

@ -57,7 +57,6 @@ MixerGroupTabs::compute_tabs () const
Tab tab;
tab.from = 0;
tab.group = 0;
int32_t x = 0;
TreeModel::Children rows = _mixer->track_model->children ();
@ -80,9 +79,10 @@ MixerGroupTabs::compute_tabs () const
#endif
std::shared_ptr<RouteGroup> g = s->route_group ();
std::shared_ptr<RouteGroup> tab_group = s->route_group ();
if (g != tab.group) {
if (tab.group) {
if (g != tab_group) {
if (tab_group) {
tab.to = x;
tabs.push_back (tab);
}
@ -100,7 +100,7 @@ MixerGroupTabs::compute_tabs () const
x += ww;
}
if (tab.group) {
if (tab.group.lock()) {
tab.to = x;
tabs.push_back (tab);
}
@ -113,10 +113,11 @@ MixerGroupTabs::draw_tab (cairo_t* cr, Tab const & tab)
{
double const arc_radius = get_height();
double r, g, b, a;
std::shared_ptr<RouteGroup> tab_group (tab.group.lock());
if (tab.group && tab.group->is_active()) {
if (tab_group && tab_group->is_active()) {
Gtkmm2ext::color_to_rgba (tab.color, r, g, b, a);
} else if (!tab.group && _dragging_new_tab) {
} else if (!tab_group && _dragging_new_tab) {
Gdk::Color col = ARDOUR_UI_UTILS::round_robin_palette_color (true);
color_t ct = Gtkmm2ext::gdk_color_to_rgba (col);
Gtkmm2ext::color_to_rgba (ct, r, g, b, a);
@ -133,14 +134,14 @@ MixerGroupTabs::draw_tab (cairo_t* cr, Tab const & tab)
cairo_line_to (cr, tab.from, get_height());
cairo_fill (cr);
if (tab.group && (tab.to - tab.from) > arc_radius) {
if (tab_group && (tab.to - tab.from) > arc_radius) {
int text_width, text_height;
Glib::RefPtr<Pango::Layout> layout;
layout = Pango::Layout::create (get_pango_context ());
layout->set_ellipsize (Pango::ELLIPSIZE_MIDDLE);
layout->set_text (tab.group->name ());
layout->set_text (tab_group->name ());
layout->set_width ((tab.to - tab.from - arc_radius) * PANGO_SCALE);
layout->get_pixel_size (text_width, text_height);
@ -209,4 +210,3 @@ MixerGroupTabs::selected_routes () const
}
return rl;
}

View file

@ -55,10 +55,11 @@ RecorderGroupTabs::compute_tabs () const
Tab tab;
tab.from = 0;
tab.group = 0;
int32_t y = 0;
std::list<TrackRecordAxis*> recorders = _recorder->visible_recorders ();
std::shared_ptr<RouteGroup> tab_group (tab.group.lock());
for (std::list<TrackRecordAxis*>::const_iterator i = recorders.begin (); i != recorders.end (); ++i) {
if ((*i)->route ()->presentation_info ().hidden ()) { // marked_for_display ()
continue;
@ -66,8 +67,8 @@ RecorderGroupTabs::compute_tabs () const
std::shared_ptr<RouteGroup> g = (*i)->route_group ();
if (g != tab.group) {
if (tab.group) {
if (g != tab_group) {
if (tab_group) {
tab.to = y;
tabs.push_back (tab);
}
@ -82,7 +83,7 @@ RecorderGroupTabs::compute_tabs () const
y += (*i)->get_height ();
}
if (tab.group) {
if (tab_group) {
tab.to = y;
tabs.push_back (tab);
}
@ -119,9 +120,10 @@ RecorderGroupTabs::draw_tab (cairo_t* cr, Tab const& tab)
double const arc_radius = get_width ();
double r, g, b, a;
if (tab.group && tab.group->is_active ()) {
std::shared_ptr<RouteGroup> tab_group (tab.group.lock());
if (tab_group && tab_group->is_active ()) {
Gtkmm2ext::color_to_rgba (tab.color, r, g, b, a);
} else if (!tab.group && _dragging_new_tab) {
} else if (!tab_group && _dragging_new_tab) {
Gdk::Color col = ARDOUR_UI_UTILS::round_robin_palette_color (true);
color_t ct = Gtkmm2ext::gdk_color_to_rgba (col);
Gtkmm2ext::color_to_rgba (ct, r, g, b, a);
@ -139,14 +141,15 @@ RecorderGroupTabs::draw_tab (cairo_t* cr, Tab const& tab)
cairo_line_to (cr, 0, tab.from + arc_radius);
cairo_fill (cr);
if (tab.group && (tab.to - tab.from) > arc_radius) {
if (tab_group && (tab.to - tab.from) > arc_radius) {
int text_width, text_height;
Glib::RefPtr<Pango::Layout> layout;
layout = Pango::Layout::create (get_pango_context ());
layout->set_ellipsize (Pango::ELLIPSIZE_MIDDLE);
layout->set_text (tab.group->name ());
layout->set_text (tab_group->name ());
layout->set_width ((tab.to - tab.from - arc_radius) * PANGO_SCALE);
layout->get_pixel_size (text_width, text_height);