From 7a5b6a5031d4c573c90d2455276aa174a665239b Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 14 Feb 2011 21:49:43 +0000 Subject: patches from lincoln to speed up the regionlist and provide region removal (causes dangling shared ptrs to regions, fix to come git-svn-id: svn://localhost/ardour2/branches/3.0@8845 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/ardour.menus.in | 6 +- gtk2_ardour/audio_region_view.cc | 116 +++++++---- gtk2_ardour/audio_region_view.h | 4 +- gtk2_ardour/editor.h | 3 + gtk2_ardour/editor_actions.cc | 7 +- gtk2_ardour/editor_drag.cc | 28 ++- gtk2_ardour/editor_drag.h | 4 +- gtk2_ardour/editor_mouse.cc | 12 +- gtk2_ardour/editor_ops.cc | 57 +++++- gtk2_ardour/editor_regions.cc | 426 +++++++++++++++------------------------ gtk2_ardour/editor_regions.h | 40 +++- libs/ardour/ardour/region.h | 36 ++-- libs/ardour/ardour/session.h | 1 + libs/ardour/region.cc | 29 ++- libs/ardour/session_state.cc | 28 ++- libs/gtkmm2ext/gtk_ui.cc | 13 +- 16 files changed, 458 insertions(+), 352 deletions(-) diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in index 88a07fcaac..476af838b0 100644 --- a/gtk2_ardour/ardour.menus.in +++ b/gtk2_ardour/ardour.menus.in @@ -540,7 +540,7 @@ - + @@ -559,7 +559,9 @@ - + + + diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index b72d95ca15..4a5a477a5c 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -269,10 +269,10 @@ AudioRegionView::~AudioRegionView () delete *i; } - for (list >::iterator i = feature_lines.begin(); i != feature_lines.end(); ++i) { + for (list >::iterator i = feature_lines.begin(); i != feature_lines.end(); ++i) { delete ((*i).second); } - + /* all waveviews etc will be destroyed when the group is destroyed */ delete gain_line; @@ -407,8 +407,8 @@ AudioRegionView::region_resized (const PropertyChange& what_changed) } /* hide transient lines that extend beyond the region end */ - - list >::iterator l; + + list >::iterator l; for (l = feature_lines.begin(); l != feature_lines.end(); ++l) { if ((*l).first > _region->length()- 1){ @@ -444,11 +444,19 @@ AudioRegionView::reset_width_dependent_items (double pixel_width) AnalysisFeatureList analysis_features = _region->transients(); AnalysisFeatureList::const_iterator i; - list >::iterator l; + + list >::iterator l; for (i = analysis_features.begin(), l = feature_lines.begin(); i != analysis_features.end() && l != feature_lines.end(); ++i, ++l) { - (*l).second->property_x1() = trackview.editor().frame_to_pixel (*i); - (*l).second->property_x2() = trackview.editor().frame_to_pixel (*i); + + float x_pos = trackview.editor().frame_to_pixel (*i); + + ArdourCanvas::Points points; + points.push_back(Gnome::Art::Point(x_pos, 2.0)); // first x-coord needs to be a non-normal value + points.push_back(Gnome::Art::Point(x_pos, _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1)); + + (*l).first = *i; + (*l).second->property_points() = points; } reset_fade_shapes (); @@ -526,13 +534,22 @@ AudioRegionView::set_height (gdouble height) reset_fade_shapes (); /* Update hights for any active feature lines */ - list >::iterator l; - + list >::iterator l; + for (l = feature_lines.begin(); l != feature_lines.end(); ++l) { - (*l).second->property_y2() = _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1; - } + + float pos_x = trackview.editor().frame_to_pixel((*l).first); + + ArdourCanvas::Points points; + + points.push_back(Gnome::Art::Point(pos_x, 2.0)); // first x-coord needs to be a non-normal value + points.push_back(Gnome::Art::Point(pos_x, _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1)); + + (*l).second->property_points() = points; + } if (fade_position_line) { + if (height < NAME_HIGHLIGHT_THRESH) { fade_position_line->property_y2() = _height - 1; } @@ -1430,31 +1447,55 @@ AudioRegionView::transients_changed () AnalysisFeatureList analysis_features = _region->transients(); while (feature_lines.size() < analysis_features.size()) { - ArdourCanvas::SimpleLine* l = new ArdourCanvas::SimpleLine (*group); - l->property_color_rgba() = (guint) ARDOUR_UI::config()->canvasvar_ZeroLine.get(); - feature_lines.push_back (make_pair(0, l)); + + ArdourCanvas::Line* canvas_item = new ArdourCanvas::Line(*group); + + ArdourCanvas::Points points; + + points.push_back(Gnome::Art::Point(-1.0, 2.0)); // first x-coord needs to be a non-normal value + points.push_back(Gnome::Art::Point(1.0, _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1)); + + canvas_item->property_points() = points; + canvas_item->property_width_pixels() = 1; + canvas_item->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_ZeroLine.get(); + canvas_item->property_first_arrowhead() = TRUE; + canvas_item->property_last_arrowhead() = TRUE; + canvas_item->property_arrow_shape_a() = 11.0; + canvas_item->property_arrow_shape_b() = 0.0; + canvas_item->property_arrow_shape_c() = 4.0; + + canvas_item->raise_to_top (); + canvas_item->show (); + + canvas_item->set_data ("regionview", this); + canvas_item->signal_event().connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_feature_line_event), canvas_item, this)); + + feature_lines.push_back (make_pair(0, canvas_item)); } while (feature_lines.size() > analysis_features.size()) { - ArdourCanvas::SimpleLine *line = feature_lines.back().second; + ArdourCanvas::Line* line = feature_lines.back().second; feature_lines.pop_back (); delete line; } AnalysisFeatureList::const_iterator i; - list >::iterator l; - + list >::iterator l; + for (i = analysis_features.begin(), l = feature_lines.begin(); i != analysis_features.end() && l != feature_lines.end(); ++i, ++l) { - (*l).first = *i; - (*l).second->property_x1() = trackview.editor().frame_to_pixel (*i); - (*l).second->property_x2() = trackview.editor().frame_to_pixel (*i); - (*l).second->property_y1() = 2; - (*l).second->property_y2() = _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1; - (*l).second->set_data("regionview", this); - (*l).second->show (); - (*l).second->raise_to_top (); + + ArdourCanvas::Points points; + + float *pos = new float; + *pos = trackview.editor().frame_to_pixel (*i); - (*l).second->signal_event().connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_feature_line_event), (*l).second, this)); + points.push_back(Gnome::Art::Point(*pos, 2.0)); // first x-coord needs to be a non-normal value + points.push_back(Gnome::Art::Point(*pos, _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1)); + + (*l).second->property_points() = points; + (*l).second->set_data ("position", pos); + + (*l).first = *i; } } @@ -1462,12 +1503,16 @@ void AudioRegionView::update_transient(float /*old_pos*/, float new_pos) { /* Find frame at old pos, calulate new frame then update region transients*/ - list >::iterator l; + list >::iterator l; for (l = feature_lines.begin(); l != feature_lines.end(); ++l) { - /* Simple line x1 has been updated in drag so we compare to new_pos */ - if (rint(new_pos) == rint((*l).second->property_x1())) { - + + /* Line has been updated in drag so we compare to new_pos */ + + float* pos = (float*) (*l).second->get_data ("position"); + + if (rint(new_pos) == rint(*pos)) { + framepos_t old_frame = (*l).first; framepos_t new_frame = trackview.editor().pixel_to_frame (new_pos); @@ -1482,12 +1527,15 @@ void AudioRegionView::remove_transient(float pos) { /* Find frame at old pos, calulate new frame then update region transients*/ - list >::iterator l; + list >::iterator l; for (l = feature_lines.begin(); l != feature_lines.end(); ++l) { - /* Simple line x1 has been updated in drag so we compare to new_pos */ - if (rint(pos) == rint((*l).second->property_x1())) { - _region->remove_transient ((*l).first); + + /* Line has been updated in drag so we compare to new_pos */ + float *line_pos = (float*) (*l).second->get_data ("position"); + + if (rint(pos) == rint(*line_pos)) { + _region->remove_transient ((*l).first); break; } } diff --git a/gtk2_ardour/audio_region_view.h b/gtk2_ardour/audio_region_view.h index f7b8404d7b..a2ec896a16 100644 --- a/gtk2_ardour/audio_region_view.h +++ b/gtk2_ardour/audio_region_view.h @@ -135,9 +135,9 @@ class AudioRegionView : public RegionView std::vector waves; std::vector tmp_waves; ///< see ::create_waves() + + std::list > feature_lines; - std::list > feature_lines; - ArdourCanvas::Polygon* sync_mark; ///< polgyon for sync position ArdourCanvas::SimpleLine* zero_line; ArdourCanvas::Polygon* fade_in_shape; diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 256c8e296c..6903cd20c9 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1385,6 +1385,9 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD bool canvas_markerview_item_view_event(GdkEvent* event, ArdourCanvas::Item*,MarkerView*); bool canvas_markerview_start_handle_event(GdkEvent* event, ArdourCanvas::Item*,MarkerView*); bool canvas_markerview_end_handle_event(GdkEvent* event, ArdourCanvas::Item*,MarkerView*); + + PBD::Signal0 EditorFreeze; + PBD::Signal0 EditorThaw; private: friend class DragManager; diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 6f1579bb5a..c3a62cb63f 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -631,13 +631,16 @@ Editor::register_actions () act = ActionManager::register_action (rl_actions, X_("rlAudition"), _("Audition"), sigc::mem_fun(*this, &Editor::audition_region_from_region_list)); ActionManager::region_list_selection_sensitive_actions.push_back (act); + act = ActionManager::register_action (rl_actions, X_("rlHide"), _("Hide"), sigc::mem_fun(*this, &Editor::hide_region_from_region_list)); ActionManager::region_list_selection_sensitive_actions.push_back (act); + act = ActionManager::register_action (rl_actions, X_("rlShow"), _("Show"), sigc::mem_fun(*this, &Editor::show_region_in_region_list)); ActionManager::region_list_selection_sensitive_actions.push_back (act); + ActionManager::register_toggle_action (rl_actions, X_("rlShowAll"), _("Show All"), sigc::mem_fun(*_regions, &EditorRegions::toggle_full)); ActionManager::register_toggle_action (rl_actions, X_("rlShowAuto"), _("Show Automatic Regions"), sigc::mem_fun (*_regions, &EditorRegions::toggle_show_auto_regions)); - + ActionManager::register_radio_action (rl_actions, sort_order_group, X_("SortAscending"), _("Ascending"), sigc::bind (sigc::mem_fun (*_regions, &EditorRegions::reset_sort_direction), true)); ActionManager::register_radio_action (rl_actions, sort_order_group, X_("SortDescending"), _("Descending"), @@ -664,6 +667,7 @@ Editor::register_actions () ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortBySourceFilesystem"), _("By Source Filesystem"), sigc::bind (sigc::mem_fun (*_regions, &EditorRegions::reset_sort_type), BySourceFileFS, false)); + ActionManager::register_action (rl_actions, X_("removeUnusedRegions"), _("Delete Unused"), sigc::mem_fun(*_regions, &EditorRegions::delete_unused_regions)); /* the next two are duplicate items with different names for use in two different contexts */ @@ -747,6 +751,7 @@ Editor::toggle_ruler_visibility (RulerType rt) } Glib::RefPtr act = ActionManager::get_action (X_("Rulers"), action); + if (act) { Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); update_ruler_visibility (); diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index b06545c32b..f0e53ab584 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -2900,7 +2900,7 @@ FeatureLineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) { Drag::start_grab (event); - _line = reinterpret_cast (_item); + _line = reinterpret_cast (_item); assert (_line); /* need to get x coordinate in terms of parent (AudioRegionView) origin. */ @@ -2913,10 +2913,10 @@ FeatureLineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) /* store grab start in parent frame */ _region_view_grab_x = cx; - _before = _line->property_x1(); + _before = *(float*) _item->get_data ("position"); _arv = reinterpret_cast (_item->get_data ("regionview")); - + _max_x = _editor->frame_to_pixel(_arv->get_duration()); } @@ -2938,17 +2938,30 @@ FeatureLineDrag::motion (GdkEvent*, bool) cx = 0; } - _line->property_x1() = cx; - _line->property_x2() = cx; + ArdourCanvas::Points points; + + double x1 = 0, x2 = 0, y1 = 0, y2 = 0; + + _line->get_bounds(x1, y2, x2, y2); + + points.push_back(Gnome::Art::Point(cx, 2.0)); // first x-coord needs to be a non-normal value + points.push_back(Gnome::Art::Point(cx, y2 - y1)); - _before = _line->property_x1(); + _line->property_points() = points; + + float *pos = new float; + *pos = cx; + + _line->set_data ("position", pos); + + _before = cx; } void FeatureLineDrag::finished (GdkEvent*, bool) { _arv = reinterpret_cast (_item->get_data ("regionview")); - _arv->update_transient(_before, _line->property_x1()); + _arv->update_transient(_before, _before); } void @@ -3049,6 +3062,7 @@ RubberbandSelectDrag::finished (GdkEvent* event, bool movement_occurred) } _editor->commit_reversible_command (); + } else { if (!getenv("ARDOUR_SAE")) { _editor->selection->clear_tracks(); diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index ab81db5a63..ce8a1370f4 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -731,13 +731,13 @@ public: private: - ArdourCanvas::SimpleLine* _line; + ArdourCanvas::Line* _line; AudioRegionView* _arv; double _region_view_grab_x; double _cumulative_x_drag; - uint32_t _before; + float _before; uint32_t _max_x; }; diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 2769a80570..6e5f8071b0 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -1462,7 +1462,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT break; case MouseAudition: - set_canvas_cursor (current_canvas_cursor); + set_canvas_cursor (current_canvas_cursor); if (scrubbing_direction == 0) { /* no drag, just a click */ switch (item_type) { @@ -1714,8 +1714,8 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ break; case FeatureLineItem: { - ArdourCanvas::SimpleLine *line = dynamic_cast (item); - line->property_color_rgba() = 0xFF0000FF; + ArdourCanvas::Line *line = dynamic_cast (item); + line->property_fill_color_rgba() = 0xFF0000FF; } break; case SelectionItem: @@ -1874,8 +1874,8 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ break; case FeatureLineItem: { - ArdourCanvas::SimpleLine *line = dynamic_cast (item); - line->property_color_rgba() = (guint) ARDOUR_UI::config()->canvasvar_ZeroLine.get();; + ArdourCanvas::Line *line = dynamic_cast (item); + line->property_fill_color_rgba() = (guint) ARDOUR_UI::config()->canvasvar_ZeroLine.get();; } break; @@ -2477,7 +2477,7 @@ Editor::mouse_brush_insert_region (RegionView* rv, framepos_t pos) double speed = rtv->track()->speed(); playlist->clear_changes (); - boost::shared_ptr new_region (RegionFactory::create (rv->region())); + boost::shared_ptr new_region (RegionFactory::create (rv->region(), true)); playlist->add_region (new_region, (framepos_t) (pos * speed)); _session->add_command (new StatefulDiffCommand (playlist)); diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index d15180fd42..ede62d8d9b 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -120,6 +120,8 @@ Editor::redo (uint32_t n) void Editor::split_regions_at (framepos_t where, RegionSelection& regions) { + bool frozen = false; + list > used_playlists; if (regions.empty()) { @@ -142,6 +144,9 @@ Editor::split_regions_at (framepos_t where, RegionSelection& regions) } } else { snap_to (where); + + frozen = true; + EditorFreeze(); /* Emit Signal */ } for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) { @@ -191,6 +196,10 @@ Editor::split_regions_at (framepos_t where, RegionSelection& regions) } commit_reversible_command (); + + if (frozen){ + EditorThaw(); /* Emit Signal */ + } } boost::shared_ptr @@ -5851,8 +5860,9 @@ Editor::split_region_at_points (boost::shared_ptr r, AnalysisFeatureList plist.add (ARDOUR::Properties::layer, 0); boost::shared_ptr nr = RegionFactory::create (r->sources(), plist, false); + pl->add_region (nr, r->position() + pos); - + if (select_new) { new_regions.push_front(nr); } @@ -5924,16 +5934,18 @@ Editor::remove_transient(ArdourCanvas::Item* item) return; } - ArdourCanvas::SimpleLine* _line = reinterpret_cast (item); + ArdourCanvas::Line* _line = reinterpret_cast (item); assert (_line); AudioRegionView* _arv = reinterpret_cast (item->get_data ("regionview")); - _arv->remove_transient(_line->property_x1()); + _arv->remove_transient (*(float*) _line->get_data ("position")); } void Editor::snap_regions_to_grid () { + list > used_playlists; + RegionSelection rs = get_regions_from_selection_and_entered (); if (!_session || rs.empty()) { @@ -5943,17 +5955,36 @@ Editor::snap_regions_to_grid () _session->begin_reversible_command (_("snap regions to grid")); for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { + + boost::shared_ptr pl = (*r)->region()->playlist(); + + if (!pl->frozen()) { + /* we haven't seen this playlist before */ + + /* remember used playlists so we can thaw them later */ + used_playlists.push_back(pl); + pl->freeze(); + } + framepos_t start_frame = (*r)->region()->first_frame (); snap_to (start_frame); (*r)->region()->set_position (start_frame, this); } + while (used_playlists.size() > 0) { + list >::iterator i = used_playlists.begin(); + (*i)->thaw(); + used_playlists.pop_front(); + } + _session->commit_reversible_command (); } void Editor::close_region_gaps () -{ +{ + list > used_playlists; + RegionSelection rs = get_regions_from_selection_and_entered (); if (!_session || rs.empty()) { @@ -6007,13 +6038,23 @@ Editor::close_region_gaps () /* Iterate over the region list and make adjacent regions overlap by crossfade_len_ms */ _session->begin_reversible_command (_("close region gaps")); - + int idx = 0; boost::shared_ptr last_region; rs.sort_by_position_and_track(); for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { + + boost::shared_ptr pl = (*r)->region()->playlist(); + + if (!pl->frozen()) { + /* we haven't seen this playlist before */ + + /* remember used playlists so we can thaw them later */ + used_playlists.push_back(pl); + pl->freeze(); + } framepos_t position = (*r)->region()->position(); @@ -6031,6 +6072,12 @@ Editor::close_region_gaps () idx++; } + while (used_playlists.size() > 0) { + list >::iterator i = used_playlists.begin(); + (*i)->thaw(); + used_playlists.pop_front(); + } + _session->commit_reversible_command (); } diff --git a/gtk2_ardour/editor_regions.cc b/gtk2_ardour/editor_regions.cc index 357bb7295e..e4798650b1 100644 --- a/gtk2_ardour/editor_regions.cc +++ b/gtk2_ardour/editor_regions.cc @@ -34,6 +34,7 @@ #include "ardour/silentfilesource.h" #include "ardour/profile.h" +#include "gtkmm2ext/choice.h" #include "gtkmm2ext/treeutils.h" #include "editor.h" @@ -72,6 +73,7 @@ EditorRegions::EditorRegions (Editor* e) _display.set_size_request (100, -1); _display.set_name ("RegionListDisplay"); _display.set_rules_hint (true); + /* Try to prevent single mouse presses from initiating edits. This relies on a hack in gtktreeview.c:gtk_treeview_button_press() */ @@ -117,24 +119,28 @@ EditorRegions::EditorRegions (Editor* e) CellRendererToggle* locked_cell = dynamic_cast (_display.get_column_cell_renderer (7)); locked_cell->property_activatable() = true; locked_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRegions::locked_changed)); + TreeViewColumn* locked_col = _display.get_column (7); locked_col->add_attribute (locked_cell->property_visible(), _columns.property_toggles_visible); CellRendererToggle* glued_cell = dynamic_cast (_display.get_column_cell_renderer (8)); glued_cell->property_activatable() = true; glued_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRegions::glued_changed)); + TreeViewColumn* glued_col = _display.get_column (8); glued_col->add_attribute (glued_cell->property_visible(), _columns.property_toggles_visible); CellRendererToggle* muted_cell = dynamic_cast (_display.get_column_cell_renderer (9)); muted_cell->property_activatable() = true; muted_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRegions::muted_changed)); + TreeViewColumn* muted_col = _display.get_column (9); muted_col->add_attribute (muted_cell->property_visible(), _columns.property_toggles_visible); CellRendererToggle* opaque_cell = dynamic_cast (_display.get_column_cell_renderer (10)); opaque_cell->property_activatable() = true; opaque_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRegions::opaque_changed)); + TreeViewColumn* opaque_col = _display.get_column (10); opaque_col->add_attribute (opaque_cell->property_visible(), _columns.property_toggles_visible); @@ -171,6 +177,9 @@ EditorRegions::EditorRegions (Editor* e) ARDOUR_UI::instance()->secondary_clock.mode_changed.connect (sigc::mem_fun(*this, &EditorRegions::update_all_rows)); ARDOUR::Region::RegionPropertyChanged.connect (region_property_connection, MISSING_INVALIDATOR, ui_bind (&EditorRegions::region_changed, this, _1, _2), gui_context()); ARDOUR::RegionFactory::CheckNewRegion.connect (check_new_region_connection, MISSING_INVALIDATOR, ui_bind (&EditorRegions::add_region, this, _1), gui_context()); + + e->EditorFreeze.connect (editor_freeze_connection, MISSING_INVALIDATOR, ui_bind (&EditorRegions::freeze_tree_model, this), gui_context()); + e->EditorThaw.connect (editor_thaw_connection, MISSING_INVALIDATOR, ui_bind (&EditorRegions::thaw_tree_model, this), gui_context()); } bool @@ -237,14 +246,6 @@ EditorRegions::set_session (ARDOUR::Session* s) redisplay (); } -void -EditorRegions::add_regions (vector >& regions) -{ - for (vector >::iterator x = regions.begin(); x != regions.end(); ++x) { - add_region (*x); - } -} - void EditorRegions::add_region (boost::shared_ptr region) { @@ -262,6 +263,7 @@ EditorRegions::add_region (boost::shared_ptr region) } if (region->hidden()) { + TreeModel::iterator iter = _model->get_iter ("0"); TreeModel::Row parent; TreeModel::Row child; @@ -282,6 +284,7 @@ EditorRegions::add_region (boost::shared_ptr region) parent = *iter; } } + row = *(_model->append (parent.children())); } else if (region->whole_file()) { @@ -357,31 +360,29 @@ EditorRegions::add_region (boost::shared_ptr region) } } - if (region->automatic()) { - return; - } - - } else { + region_row_map.insert(pair, Gtk::TreeModel::RowReference>(region, TreeRowReference(_model, TreePath (row))) ); + parent_regions_sources_map.insert(pair(region->source_string(), TreeRowReference(_model, TreePath (row))) ); - /* find parent node, add as new child */ + return; + } else { + // find parent node, add as new child TreeModel::iterator i; TreeModel::Children rows = _model->children(); - bool found_parent = false; - - for (i = rows.begin(); i != rows.end(); ++i) { - boost::shared_ptr r = (*i)[_columns.region]; - - if (r && r->whole_file()) { - - if (region->source_equivalent (r)) { - found_parent = true; - } - } + boost::unordered_map::iterator it; + + it = parent_regions_sources_map.find (region->source_string()); + + if (it != parent_regions_sources_map.end()){ + + TreeModel::iterator j = _model->get_iter ((*it).second.get_path()); + TreeModel::iterator ii; - TreeModel::Children subrows = (*i).children(); + TreeModel::Children subrows = (*j).children(); + /* XXXX: should we be accounting for all regions? */ + /* for (ii = subrows.begin(); ii != subrows.end(); ++ii) { boost::shared_ptr rr = (*ii)[_columns.region]; @@ -389,15 +390,12 @@ EditorRegions::add_region (boost::shared_ptr region) return; } } - - if (found_parent) { - row = *(_model->append ((*i).children())); - break; - } + */ + + row = *(_model->insert (subrows.end())); } - - if (!found_parent) { - row = *(_model->append()); + else { + row = *(_model->append()); } row[_columns.property_toggles_visible] = true; @@ -405,9 +403,37 @@ EditorRegions::add_region (boost::shared_ptr region) row[_columns.region] = region; + region_row_map.insert(pair, Gtk::TreeModel::RowReference>(region, TreeRowReference(_model, TreePath (row))) ); + populate_row(region, (*row)); } +void +EditorRegions::delete_unused_regions () +{ + vector choices; + string prompt; + + if (!_session) { + return; + } + + prompt = _("Do you really want to remove unused regions?" + "\n(This is destructive and cannot be undone)"); + + choices.push_back (_("No, do nothing.")); + choices.push_back (_("Yes, remove.")); + + Gtkmm2ext::Choice prompter (_("Remove unused regions"), prompt, choices); + + if (prompter.run () == 1) { + _no_redisplay = true; + _session->cleanup_regions (); + _no_redisplay = false; + redisplay (); + } +} + void EditorRegions::region_changed (boost::shared_ptr r, const PropertyChange& what_changed) { @@ -424,101 +450,48 @@ EditorRegions::region_changed (boost::shared_ptr r, const PropertyChange our_interests.add (ARDOUR::Properties::fade_in); our_interests.add (ARDOUR::Properties::fade_out); - if (last_row != 0) { - - TreeModel::iterator j = _model->get_iter (last_row.get_path()); - boost::shared_ptr c = (*j)[_columns.region]; - - if (c == r) { - populate_row (r, (*j)); - - if (what_changed.contains (ARDOUR::Properties::hidden)) { - redisplay (); - } - - return; - } - } - if (what_changed.contains (our_interests)) { - /* find the region in our model and update its row */ - TreeModel::Children rows = _model->children (); - TreeModel::iterator i = rows.begin (); - - while (i != rows.end ()) { + if (last_row != 0) { - TreeModel::Children children = (*i)->children (); - TreeModel::iterator found = children.end (); - - boost::shared_ptr c = (*i)[_columns.region]; + TreeModel::iterator j = _model->get_iter (last_row.get_path()); + boost::shared_ptr c = (*j)[_columns.region]; if (c == r) { - - /* check this row */ - last_row = TreeRowReference (_model, TreePath (i)); - found = i; - - } else { - - /* check its children */ + populate_row (r, (*j)); - found = children.begin (); - while (found != children.end()) { - - boost::shared_ptr c = (*found)[_columns.region]; - - if (c == r) { - last_row = TreeRowReference(_model, TreePath (found)); - break; - } - ++found; + if (what_changed.contains (ARDOUR::Properties::hidden)) { + redisplay (); } + + return; } + } + + RegionRowMap::iterator it; + + it = region_row_map.find (r); + + if (it != region_row_map.end()){ - if (found != children.end()) { - - boost::shared_ptr audioregion = boost::dynamic_pointer_cast(r); - uint32_t used = _editor->get_regionview_count_from_region_list (r); + TreeModel::iterator j = _model->get_iter ((*it).second.get_path()); + boost::shared_ptr c = (*j)[_columns.region]; - if (what_changed.contains (ARDOUR::Properties::name)) { - populate_row_name (r, *found); - } - if (what_changed.contains (ARDOUR::Properties::position)) { - populate_row_position (r, *found, used); - populate_row_end (r, *found, used); - } - if (what_changed.contains (ARDOUR::Properties::length)) { - populate_row_end (r, *found, used); - populate_row_length (r, *found); - } - if (what_changed.contains (ARDOUR::Properties::start)) { - populate_row_length (r, *found); - } - if (what_changed.contains (ARDOUR::Properties::locked)) { - populate_row_locked (r, *found, used); - } - if (what_changed.contains (ARDOUR::Properties::position_lock_style)) { - populate_row_glued (r, *found, used); - } - if (what_changed.contains (ARDOUR::Properties::muted)) { - populate_row_muted (r, *found, used); - } - if (what_changed.contains (ARDOUR::Properties::opaque)) { - populate_row_opaque (r, *found, used); - } - if (what_changed.contains (ARDOUR::Properties::fade_in)) { - populate_row_fade_in (r, *found, used, audioregion); - } - if (what_changed.contains (ARDOUR::Properties::fade_out)) { - populate_row_fade_out (r, *found, used, audioregion); + if (c == r) { + populate_row (r, (*j)); + + if (what_changed.contains (ARDOUR::Properties::hidden)) { + redisplay (); } + + return; + } + } - break; - } + /* find the region in our model and update its row */ + TreeModel::Children rows = _model->children (); + TreeModel::iterator i = rows.begin (); - ++i; - } } if (what_changed.contains (ARDOUR::Properties::hidden)) { @@ -576,67 +549,19 @@ EditorRegions::selection_changed () void EditorRegions::set_selected (RegionSelection& regions) { - TreeModel::Children rows = _model->children(); - - for (RegionSelection::iterator iter = regions.begin(); iter != regions.end(); ++iter) { + for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) { - TreeModel::iterator i; + boost::shared_ptr r ((*i)->region()); - boost::shared_ptr r ((*iter)->region()); - - for (i = rows.begin(); i != rows.end(); ++i) { - - boost::shared_ptr compared_region = (*i)[_columns.region]; - - if (r == compared_region) { - _display.get_selection()->select(*i); - break; - } - - if (!(*i).children().empty()) { - if (set_selected_in_subrow(r, (*i), 2)) { - break; - } - } - } - } -} - -bool -EditorRegions::set_selected_in_subrow (boost::shared_ptr region, TreeModel::Row const &parent_row, int level) -{ - TreeModel::iterator i; - TreeModel::Children subrows = (*parent_row).children(); - - for (i = subrows.begin(); i != subrows.end(); ++i) { - - boost::shared_ptr compared_region = (*i)[_columns.region]; - - if (region == compared_region) { - _display.get_selection()->select(*i); - return true; - } + RegionRowMap::iterator it; + + it = region_row_map.find (r); - if (!(*i).children().empty()) { - if (set_selected_in_subrow (region, (*i), level + 1)) { - return true; - } + if (it != region_row_map.end()){ + TreeModel::iterator j = _model->get_iter ((*it).second.get_path()); + _display.get_selection()->select(*j); } } - - return false; -} - -void -EditorRegions::insert_into_tmp_regionlist(boost::shared_ptr region) -{ - /* keep all whole files at the beginning */ - - if (region->whole_file()) { - tmp_region_list.push_front (region); - } else { - tmp_region_list.push_back (region); - } } void @@ -655,23 +580,36 @@ EditorRegions::redisplay () _display.set_model (Glib::RefPtr(0)); _model->clear (); + _model->set_sort_column (-2, SORT_ASCENDING); //Disable sorting to gain performance + + region_row_map.clear(); + parent_regions_sources_map.clear(); + /* now add everything we have, via a temporary list used to help with sorting */ - tmp_region_list.clear(); - const RegionFactory::RegionMap& regions (RegionFactory::regions()); + for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) { - insert_into_tmp_regionlist (i->second); + + if ( i->second->whole_file()) { + /* add automatic regions first so that children can find their parents as we add them */ + add_region (i->second); + continue; + } + + tmp_region_list.push_front (i->second); } for (list >::iterator r = tmp_region_list.begin(); r != tmp_region_list.end(); ++r) { add_region (*r); } - tmp_region_list.clear(); - + + _model->set_sort_column (0, SORT_ASCENDING); // renabale sorting _display.set_model (_model); + tmp_region_list.clear(); + if (tree_expanded) { _display.expand_all(); } @@ -684,59 +622,15 @@ EditorRegions::update_row (boost::shared_ptr region) return; } - TreeModel::iterator i; - TreeModel::Children rows = _model->children(); + RegionRowMap::iterator it; - return; + it = region_row_map.find (region); - for (i = rows.begin(); i != rows.end(); ++i) { + if (it != region_row_map.end()){ -// cerr << "Level 1: Compare " << region->name() << " with parent " << (*i)[_columns.name] << "\n"; - - boost::shared_ptr compared_region = (*i)[_columns.region]; - - if (region == compared_region) { -// cerr << "Matched\n"; - populate_row(region, (*i)); - return; - } - - if (!(*i).children().empty()) { - if (update_subrows(region, (*i), 2)) { - return; - } - } + TreeModel::iterator j = _model->get_iter ((*it).second.get_path()); + populate_row(region, (*j)); } - -// cerr << "Returning - No match\n"; -} - -bool -EditorRegions::update_subrows (boost::shared_ptr region, TreeModel::Row const &parent_row, int level) -{ - TreeModel::iterator i; - TreeModel::Children subrows = (*parent_row).children(); - - for (i = subrows.begin(); i != subrows.end(); ++i) { - -// cerr << "Level " << level << ": Compare " << region->name() << " with child " << (*i)[_columns.name] << "\n"; - - boost::shared_ptr compared_region = (*i)[_columns.region]; - - if (region == compared_region) { - populate_row(region, (*i)); -// cerr << "Matched\n"; - return true; - } - - if (!(*i).children().empty()) { - if (update_subrows (region, (*i), level + 1)) { - return true; - } - } - } - - return false; } void @@ -745,40 +639,17 @@ EditorRegions::update_all_rows () if (!_session) { return; } - - TreeModel::iterator i; - TreeModel::Children rows = _model->children(); - - for (i = rows.begin(); i != rows.end(); ++i) { - - boost::shared_ptr region = (*i)[_columns.region]; - - if (!region->automatic()) { - populate_row(region, (*i)); - } - - if (!(*i).children().empty()) { - update_all_subrows ((*i), 2); - } - } -} - -void -EditorRegions::update_all_subrows (TreeModel::Row const &parent_row, int level) -{ - TreeModel::iterator i; - TreeModel::Children subrows = (*parent_row).children(); - for (i = subrows.begin(); i != subrows.end(); ++i) { + RegionRowMap::iterator i; - boost::shared_ptr region = (*i)[_columns.region]; + for (i = region_row_map.begin(); i != region_row_map.end(); ++i) { + TreeModel::iterator j = _model->get_iter ((*i).second.get_path()); + + boost::shared_ptr region = (*j)[_columns.region]; + if (!region->automatic()) { - populate_row(region, (*i)); - } - - if (!(*i).children().empty()) { - update_all_subrows ((*i), level + 1); + populate_row(region, (*j)); } } } @@ -827,8 +698,10 @@ void EditorRegions::populate_row (boost::shared_ptr region, TreeModel::Row const &row) { boost::shared_ptr audioregion = boost::dynamic_pointer_cast(region); - uint32_t used = _session->playlists->region_use_count (region); - + //uint32_t used = _session->playlists->region_use_count (region); + /* Presently a region is only used once so let's save on the sequential scan to determine use count */ + uint32_t used = 1; + populate_row_position (region, row, used); populate_row_end (region, row, used); populate_row_sync (region, row, used); @@ -1448,6 +1321,25 @@ EditorRegions::get_single_selection () return (*iter)[_columns.region]; } +void +EditorRegions::freeze_tree_model (){ + + _display.set_model (Glib::RefPtr(0)); + _model->set_sort_column (-2, SORT_ASCENDING); //Disable sorting to gain performance + +} + +void +EditorRegions::thaw_tree_model (){ + + _model->set_sort_column (0, SORT_ASCENDING); // renabale sorting + _display.set_model (_model); + + if (toggle_full_action()->get_active()) { + _display.expand_all(); + } +} + void EditorRegions::locked_changed (std::string const & path) { @@ -1515,7 +1407,7 @@ EditorRegions::get_state () const return *node; } - + void EditorRegions::set_state (const XMLNode & node) { @@ -1526,28 +1418,35 @@ EditorRegions::set_state (const XMLNode & node) } XMLProperty const * p = node.property (X_("sort-type")); + if (p) { Editing::RegionListSortType const t = static_cast (string_2_enum (p->value(), _sort_type)); + if (_sort_type != t) { changed = true; } + reset_sort_type (t, true); RefPtr ract = sort_type_action (t); ract->set_active (); } p = node.property (X_("sort-ascending")); + if (p) { bool const yn = string_is_affirmative (p->value ()); SortType old_sort_type; int old_sort_column; _model->get_sort_column_id (old_sort_column, old_sort_type); + if (old_sort_type != (yn ? SORT_ASCENDING : SORT_DESCENDING)) { changed = true; } + reset_sort_direction (yn); RefPtr act; + if (yn) { act = ActionManager::get_action (X_("RegionList"), X_("SortAscending")); } else { @@ -1560,9 +1459,11 @@ EditorRegions::set_state (const XMLNode & node) p = node.property (X_("show-all")); if (p) { bool const yn = string_is_affirmative (p->value ()); + if (expanded != yn) { changed = true; } + set_full (yn); toggle_full_action()->set_active (yn); } @@ -1570,6 +1471,7 @@ EditorRegions::set_state (const XMLNode & node) p = node.property (X_("show-automatic-regions")); if (p) { bool const yn = string_is_affirmative (p->value ()); + if (yn != _show_automatic_regions) { _show_automatic_regions = yn; toggle_show_auto_regions_action()->set_active (yn); @@ -1642,6 +1544,12 @@ EditorRegions::show_action () const return ActionManager::get_action (X_("RegionList"), X_("rlShow")); } +RefPtr +EditorRegions::delete_unused_regions_action () const +{ + return ActionManager::get_action (X_("RegionList"), X_("removeUnusedRegions")); +} + RefPtr EditorRegions::toggle_full_action () const { diff --git a/gtk2_ardour/editor_regions.h b/gtk2_ardour/editor_regions.h index 0643befbdf..c9d2f8714e 100644 --- a/gtk2_ardour/editor_regions.h +++ b/gtk2_ardour/editor_regions.h @@ -20,6 +20,7 @@ #define __gtk_ardour_editor_regions_h__ #include "editor_component.h" +#include class EditorRegions : public EditorComponent, public ARDOUR::SessionHandlePtr { @@ -66,6 +67,8 @@ public: void unselect_all () { _display.get_selection()->unselect_all (); } + + void delete_unused_regions(); XMLNode& get_state () const; void set_state (const XMLNode &); @@ -115,12 +118,13 @@ private: Gtk::TreeModel::RowReference last_row; + void freeze_tree_model (); + void thaw_tree_model (); void region_changed (boost::shared_ptr, PBD::PropertyChange const &); void selection_changed (); sigc::connection _change_connection; - - bool set_selected_in_subrow (boost::shared_ptr, Gtk::TreeModel::Row const &, int); + bool selection_filter (const Glib::RefPtr& model, const Gtk::TreeModel::Path& path, bool yn); Gtk::Widget* old_focus; @@ -135,10 +139,12 @@ private: bool key_press (GdkEventKey *); bool button_press (GdkEventButton *); + bool focus_in (GdkEventFocus*); bool focus_out (GdkEventFocus*); bool enter_notify (GdkEventCrossing*); bool leave_notify (GdkEventCrossing*); + void show_context_menu (int button, int time); int sorter (Gtk::TreeModel::iterator, Gtk::TreeModel::iterator); @@ -146,7 +152,7 @@ private: void format_position (ARDOUR::framepos_t pos, char* buf, size_t bufsize); void add_region (boost::shared_ptr); - void add_regions (std::vector > & ); + void populate_row (boost::shared_ptr, Gtk::TreeModel::Row const &); void populate_row_used (boost::shared_ptr region, Gtk::TreeModel::Row const& row, uint32_t used); void populate_row_position (boost::shared_ptr region, Gtk::TreeModel::Row const& row, uint32_t used); @@ -162,10 +168,9 @@ private: void populate_row_name (boost::shared_ptr region, Gtk::TreeModel::Row const& row); void populate_row_source (boost::shared_ptr region, Gtk::TreeModel::Row const& row); - void update_row (boost::shared_ptr); - bool update_subrows (boost::shared_ptr, Gtk::TreeModel::Row const &, int); + void update_row (boost::shared_ptr); void update_all_rows (); - void update_all_subrows (Gtk::TreeModel::Row const &, int); + void insert_into_tmp_regionlist (boost::shared_ptr); void drag_data_received ( @@ -177,22 +182,39 @@ private: Glib::RefPtr hide_action () const; Glib::RefPtr show_action () const; + Glib::RefPtr delete_unused_regions_action() const; Glib::RefPtr toggle_full_action () const; Glib::RefPtr toggle_show_auto_regions_action () const; Gtk::Menu* _menu; Gtk::ScrolledWindow _scroller; Gtk::Frame _frame; + Gtkmm2ext::DnDTreeView > _display; + Glib::RefPtr _model; + bool _show_automatic_regions; - Editing::RegionListSortType _sort_type; + bool ignore_region_list_selection_change; + bool ignore_selected_region_change; bool _no_redisplay; + + Editing::RegionListSortType _sort_type; + std::list > tmp_region_list; + + typedef boost::unordered_map, Gtk::TreeModel::RowReference> RegionRowMap; + typedef boost::unordered_map RegionSourceMap; + + RegionRowMap region_row_map; + RegionSourceMap parent_regions_sources_map; + PBD::ScopedConnection region_property_connection; PBD::ScopedConnection check_new_region_connection; - bool ignore_region_list_selection_change; - bool ignore_selected_region_change; + + PBD::ScopedConnection editor_freeze_connection; + PBD::ScopedConnection editor_thaw_connection; + bool expanded; }; diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index 3bb5d0aac8..2639662b2e 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -139,23 +139,24 @@ class Region framepos_t first_frame () const { return _position; } framepos_t last_frame () const { return _position + _length - 1; } - bool hidden () const { return _hidden; } - bool muted () const { return _muted; } - bool opaque () const { return _opaque; } - bool locked () const { return _locked; } - bool position_locked () const { return _position_locked; } - bool valid_transients () const { return _valid_transients; } - bool automatic () const { return _automatic; } - bool whole_file () const { return _whole_file; } - bool captured () const { return !(_import || _external); } - bool can_move () const { return !_position_locked; } - bool sync_marked () const { return _sync_marked; } - bool external () const { return _external; } - bool import () const { return _import; } - - Trimmable::CanTrim can_trim () const; + bool hidden() const { return _hidden; } + bool muted() const { return _muted; } + bool opaque () const { return _opaque; } + bool locked() const { return _locked; } + bool position_locked() const { return _position_locked; } + bool valid_transients() const { return _valid_transients; } + bool automatic() const { return _automatic; } + bool whole_file() const { return _whole_file; } + bool captured() const { return !(_import || _external); } + bool can_move() const { return !_position_locked; } + bool sync_marked() const { return _sync_marked; } + bool external() const { return _external; } + bool import() const { return _import; } + + Trimmable::CanTrim can_trim() const; PositionLockStyle position_lock_style () const { return _position_lock_style; } + void set_position_lock_style (PositionLockStyle ps); void recompute_position_from_lock_style (); @@ -175,6 +176,9 @@ class Region bool region_list_equivalent (boost::shared_ptr) const; bool source_equivalent (boost::shared_ptr) const; bool uses_source (boost::shared_ptr) const; + + std::string source_string () const; + /* EDITING OPERATIONS */ @@ -223,7 +227,7 @@ class Region void source_deleted (boost::weak_ptr); boost::shared_ptr source (uint32_t n=0) const { return _sources[ (n < _sources.size()) ? n : 0 ]; } - uint32_t n_channels() const { return _sources.size(); } + uint32_t n_channels() const { return _sources.size(); } const SourceList& sources () const { return _sources; } const SourceList& master_sources () const { return _master_sources; } diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 0970e01b5c..293d9d391f 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -512,6 +512,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void add_source (boost::shared_ptr); void remove_source (boost::weak_ptr); + void cleanup_regions(); int cleanup_sources (CleanupReport&); int cleanup_trash_sources (CleanupReport&); diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 5a89707495..d711695927 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -423,6 +423,7 @@ Region::set_name (const std::string& str) if (_name != str) { SessionObject::set_name(str); // EMIT SIGNAL NameChanged() assert(_name == str); + send_change (Properties::name); } @@ -490,6 +491,7 @@ Region::first_edit () _first_edit = EditChangesNothing; send_change (Properties::name); + RegionFactory::CheckNewRegion (shared_from_this()); } } @@ -559,6 +561,7 @@ Region::set_position_lock_style (PositionLockStyle ps) } send_change (Properties::position_lock_style); + } } @@ -643,7 +646,6 @@ Region::set_position_on_top (framepos_t pos, void* /*src*/) /* do this even if the position is the same. this helps out a GUI that has moved its representation already. */ - send_change (Properties::position); } @@ -1023,6 +1025,7 @@ Region::set_sync_position (framepos_t absolute_pos) if (!property_changes_suspended()) { maybe_uncopy (); } + send_change (Properties::sync_position); } } @@ -1035,6 +1038,7 @@ Region::clear_sync_position () if (!property_changes_suspended()) { maybe_uncopy (); } + send_change (Properties::sync_position); } } @@ -1428,6 +1432,29 @@ Region::source_equivalent (boost::shared_ptr other) const return true; } +std::string +Region::source_string () const +{ + //string res = itos(_sources.size()); + + char buf[64]; + + stringstream res; + res << _sources.size() << ":"; + + SourceList::const_iterator i; + + for (i = _sources.begin(); i != _sources.end(); ++i) { + res << (*i)->id() << ":"; + } + + for (i = _master_sources.begin(); i != _master_sources.end(); ++i) { + res << (*i)->id() << ":"; + } + + return res.str(); +} + bool Region::uses_source (boost::shared_ptr source) const { diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index cb1394740c..05fdb13bec 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -2575,6 +2575,32 @@ Session::ask_about_playlist_deletion (boost::shared_ptr p) return r.get_value_or (1); } +void +Session::cleanup_regions () +{ + const RegionFactory::RegionMap& regions (RegionFactory::regions()); + + for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) { + + boost::shared_ptr audio_region = boost::dynamic_pointer_cast( i->second); + + if (!audio_region) { + continue; + } + + uint32_t used = playlists->region_use_count (audio_region); + + if (used == 0 && !audio_region->automatic()){ + RegionFactory::map_remove(i->second); + } + } + + /* dump the history list */ + _history.clear (); + + save_state (""); +} + int Session::cleanup_sources (CleanupReport& rep) { @@ -2999,7 +3025,7 @@ Session::controllable_by_descriptor (const ControllableDescriptor& desc) break; case ControllableDescriptor::Solo: - c = r->solo_control(); + c = r->solo_control(); break; case ControllableDescriptor::Mute: diff --git a/libs/gtkmm2ext/gtk_ui.cc b/libs/gtkmm2ext/gtk_ui.cc index 9736569053..035e892fba 100644 --- a/libs/gtkmm2ext/gtk_ui.cc +++ b/libs/gtkmm2ext/gtk_ui.cc @@ -147,7 +147,7 @@ UI::load_rcfile (string path, bool themechange) return -1; } - if (access (path.c_str(), R_OK)) { + if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) { error << "UI: couldn't find rc file \"" << path << '"' @@ -155,12 +155,11 @@ UI::load_rcfile (string path, bool themechange) return -1; } - RC rc (path.c_str()); - gtk_rc_reset_styles (gtk_settings_get_default()); - //vector files; - //files.push_back(path.c_str()); - //RC::set_default_files(files); - //RC::reparse_all (Gtk::Settings::get_default(), true); + RC rc (path.c_str()); + //this is buggy in gtkmm for some reason, so use C + //RC::reset_styles (Gtk::Settings::get_default()); + gtk_rc_reset_styles (gtk_settings_get_default()); + theme_changed.emit(); if (themechange) { -- cgit v1.2.3