From 8b1b1e23626602b74011819c3ec0d59ea6001413 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 16 Dec 2025 20:19:11 -0700 Subject: [PATCH] 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 makes the RouteGroup outlive the session itself. --- gtk2_ardour/editor_group_tabs.cc | 19 ++++++++++--------- gtk2_ardour/group_tabs.cc | 14 +++++++++----- gtk2_ardour/group_tabs.h | 4 ++-- gtk2_ardour/mixer_group_tabs.cc | 18 +++++++++--------- gtk2_ardour/recorder_group_tabs.cc | 19 +++++++++++-------- 5 files changed, 41 insertions(+), 33 deletions(-) diff --git a/gtk2_ardour/editor_group_tabs.cc b/gtk2_ardour/editor_group_tabs.cc index d165097e6d..a29e2a8b71 100644 --- a/gtk2_ardour/editor_group_tabs.cc +++ b/gtk2_ardour/editor_group_tabs.cc @@ -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 g ((*i)->route_group ()); + std::shared_ptr 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 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 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; } - diff --git a/gtk2_ardour/group_tabs.cc b/gtk2_ardour/group_tabs.cc index 509fa3a931..bea5e893a2 100644 --- a/gtk2_ardour/group_tabs.cc +++ b/gtk2_ardour/group_tabs.cc @@ -209,7 +209,7 @@ GroupTabs::on_button_press_event (GdkEventButton* ev) } else if (ev->button == 3) { - std::shared_ptr g (t ? t->group : nullptr); + std::shared_ptr 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 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 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); } } diff --git a/gtk2_ardour/group_tabs.h b/gtk2_ardour/group_tabs.h index 18147ce354..390a8dbb76 100644 --- a/gtk2_ardour/group_tabs.h +++ b/gtk2_ardour/group_tabs.h @@ -75,12 +75,12 @@ public: protected: struct Tab { - Tab () : group (0) {} + Tab () {} double from; double to; uint32_t color; ///< color - std::shared_ptr group; ///< route group + std::weak_ptr group; ///< route group }; /** @return Size of the widget along the primary axis */ diff --git a/gtk2_ardour/mixer_group_tabs.cc b/gtk2_ardour/mixer_group_tabs.cc index 53bac99635..b6705ef860 100644 --- a/gtk2_ardour/mixer_group_tabs.cc +++ b/gtk2_ardour/mixer_group_tabs.cc @@ -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 g = s->route_group (); + std::shared_ptr 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 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 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; } - diff --git a/gtk2_ardour/recorder_group_tabs.cc b/gtk2_ardour/recorder_group_tabs.cc index 22bd0bcc92..72db5fc15a 100644 --- a/gtk2_ardour/recorder_group_tabs.cc +++ b/gtk2_ardour/recorder_group_tabs.cc @@ -55,10 +55,11 @@ RecorderGroupTabs::compute_tabs () const Tab tab; tab.from = 0; - tab.group = 0; int32_t y = 0; std::list recorders = _recorder->visible_recorders (); + std::shared_ptr tab_group (tab.group.lock()); + for (std::list::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 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 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 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);