View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0003480 | ardour | features | public | 2010-09-25 21:44 | 2011-02-23 07:34 |
Reporter | lincoln | Assigned To | |||
Priority | normal | Severity | feature | Reproducibility | N/A |
Status | new | Resolution | open | ||
Target Version | 3.X | ||||
Summary | 0003480: Add ability to remove unused regions from session | ||||
Description | Presently Ardour will hold on to regions even if they are not being used in any playlist. As a session evolves, more and more regions are created as editing happens and some operations will slow down due to the overhead of maintaining the region list. In such cases the session will also take a long time to load or save state. The attached patch adds a menu entry in the region list context menu that allows the user to remove regions that are not being used. The patch also moves the creation of automatic regions away from the audio_diskstream to the editor_regions add_region method. This reduces the amount of signals being emitted when the transport is stopped after a capture. This is a destructive operation very similar to the clean sources function. History is cleared so it is suggested that the function is only used in cases where the region list overhead is slowing down the user. | ||||
Additional Information | Not sure if the regions need to be destroyed individually. The method may be leaky right now and require some work to address this. Having a warning dialog appear before the operation is executed may be a good idea too. | ||||
Tags | No tags attached. | ||||
2010-09-25 21:44
|
remove-unused-regions-function.patch (19,156 bytes)
Index: gtk2_ardour/editor_regions.cc =================================================================== --- gtk2_ardour/editor_regions.cc (revision 7841) +++ gtk2_ardour/editor_regions.cc (working copy) @@ -189,6 +189,7 @@ } if (region->hidden()) { + TreeModel::iterator iter = _model->get_iter ("0"); TreeModel::Row parent; TreeModel::Row child; @@ -212,38 +213,58 @@ row = *(_model->append (parent.children())); - } else if (region->whole_file()) { + } else if (!_show_automatic_regions){ + row = row = *(_model->append()); + } 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<Region> rr = (*i)[_columns.region]; + boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion>(rr); - if (rr && region->region_list_equivalent (rr)) { - return; + if (r && region->source_equivalent (r) && r->automatic()) { + + row = *(_model->append ((*i).children())); + found_parent = true; + + break; } + + TreeModel::iterator ii; + TreeModel::Children subrows = (*i).children(); + + for (ii = subrows.begin(); ii != subrows.end(); ++ii) { + boost::shared_ptr<Region> rrr = (*ii)[_columns.region]; + + if (region->region_list_equivalent (rrr)) { + return; + + } + } } - row = *(_model->append()); + if (!found_parent) { - if (missing_source) { - c.set_rgb(65535,0,0); // FIXME: error color from style + row = *(_model->append()); - } else if (region->automatic()){ - c.set_rgb(0,65535,0); // FIXME: error color from style + if (missing_source) { + c.set_rgb(65535,0,0); // FIXME: error color from style - } else { - set_color(c, rgba_from_style ("RegionListWholeFile", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL, false )); + } else { + c.set_rgb(0,65535,0); // FIXME: error color from style - } + } - row[_columns.color_] = c; + row[_columns.color_] = c; - if (region->source()->name()[0] == '/') { // external file + if (region->source()->name()[0] == '/') { // external file - if (region->whole_file()) { - boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(region->source()); str = ".../"; @@ -252,81 +273,41 @@ } else { str += region->source()->name(); } - } else { - str = region->name(); + str += region_name_from_path (region->source()->name(), true); } - } else { - str = region->name(); - } - - if (region->n_channels() > 1) { - std::stringstream foo; - foo << region->n_channels (); - str += " ["; - str += foo.str(); - str += "]"; - } - - row[_columns.name] = str; - row[_columns.region] = region; - row[_columns.property_toggles_visible] = false; - - if (missing_source) { - row[_columns.path] = _("(MISSING) ") + region->source()->name(); - - } else { - row[_columns.path] = region->source()->name(); - - } - - if (region->automatic()) { - 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<Region> rr = (*i)[_columns.region]; - boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion>(rr); - - if (r && r->whole_file()) { - - if (region->source_equivalent (r)) { - row = *(_model->append ((*i).children())); - found_parent = true; - break; - } + if (region->n_channels() > 1) { + std::stringstream foo; + foo << region->n_channels (); + str += " ["; + str += foo.str(); + str += "]"; } + + /* Create an automatic region to serve as the parent node in the tree */ + boost::shared_ptr<Region> r = RegionFactory::create (region, false, true); + + row[_columns.name] = str; + row[_columns.region] = r; + row[_columns.property_toggles_visible] = false; - TreeModel::iterator ii; - TreeModel::Children subrows = (*i).children(); + if (missing_source) { + row[_columns.path] = _("(MISSING) ") + region->source()->name(); - for (ii = subrows.begin(); ii != subrows.end(); ++ii) { - boost::shared_ptr<Region> rrr = (*ii)[_columns.region]; + } else { + row[_columns.path] = region->source()->name(); - if (region->region_list_equivalent (rrr)) { - return; - - } } + + /* Now add the region to the parent row just created */ + row = *(_model->append (row.children())); } - - if (!found_parent) { - row = *(_model->append()); - } - - row[_columns.property_toggles_visible] = true; } row[_columns.region] = region; + row[_columns.name] = region->name(); + row[_columns.property_toggles_visible] = true; populate_row(region, (*row)); } @@ -569,6 +550,7 @@ 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); } @@ -576,6 +558,7 @@ for (list<boost::shared_ptr<Region> >::iterator r = tmp_region_list.begin(); r != tmp_region_list.end(); ++r) { add_region (*r); } + tmp_region_list.clear(); _display.set_model (_model); @@ -949,7 +932,15 @@ } } + void +EditorRegions::delete_unused_regions () +{ + _session->cleanup_regions(); + redisplay(); +} + +void EditorRegions::toggle_show_auto_regions () { _show_automatic_regions = toggle_show_auto_regions_action()->get_active(); @@ -993,9 +984,12 @@ bool have_hidden = false; TreeView::Selection::ListHandle_Path rows = _display.get_selection()->get_selected_rows (); + for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) { + TreeIter t = _model->get_iter (*i); boost::shared_ptr<Region> r = (*t)[_columns.region]; + if (r) { if (r->hidden ()) { have_hidden = true; @@ -1380,6 +1374,7 @@ } XMLProperty const * p = node.property (X_("sort-type")); + if (p) { Editing::RegionListSortType const t = static_cast<Editing::RegionListSortType> (string_2_enum (p->value(), _sort_type)); if (_sort_type != t) { @@ -1391,6 +1386,7 @@ } p = node.property (X_("sort-ascending")); + if (p) { bool const yn = string_is_affirmative (p->value ()); SortType old_sort_type; @@ -1412,6 +1408,7 @@ } p = node.property (X_("show-all")); + if (p) { bool const yn = string_is_affirmative (p->value ()); if (expanded != yn) { @@ -1422,7 +1419,9 @@ } 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; @@ -1498,6 +1497,12 @@ return ActionManager::get_action (X_("RegionList"), X_("rlShow")); } +RefPtr<Action> +EditorRegions::delete_unused_regions_action () const +{ + return ActionManager::get_action (X_("RegionList"), X_("removeUnusedRegions")); +} + RefPtr<ToggleAction> EditorRegions::toggle_full_action () const { Index: gtk2_ardour/ardour.menus.in =================================================================== --- gtk2_ardour/ardour.menus.in (revision 7841) +++ gtk2_ardour/ardour.menus.in (working copy) @@ -514,7 +514,7 @@ <menuitem action='rlAudition'/> <menuitem action='rlHide'/> <menuitem action='rlShow'/> - <separator/> + <separator/> <menuitem action='rlShowAll'/> <menuitem action='rlShowAuto'/> <menu name='Sort' action='RegionListSort'> @@ -533,6 +533,8 @@ <menuitem action='SortBySourceFilesystem'/> </menu> <separator/> - <menuitem action='addExternalAudioToRegionList'/> + <menuitem action='addExternalAudioToRegionList'/> + <separator/> + <menuitem action='removeUnusedRegions'/> </popup> </ui> Index: gtk2_ardour/editor_actions.cc =================================================================== --- gtk2_ardour/editor_actions.cc (revision 7841) +++ gtk2_ardour/editor_actions.cc (working copy) @@ -801,13 +801,16 @@ 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"), @@ -834,6 +837,7 @@ 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 */ @@ -917,6 +921,7 @@ } Glib::RefPtr<Action> act = ActionManager::get_action (X_("Rulers"), action); + if (act) { Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act); update_ruler_visibility (); Index: gtk2_ardour/editor_regions.h =================================================================== --- gtk2_ardour/editor_regions.h (revision 7841) +++ gtk2_ardour/editor_regions.h (working copy) @@ -66,6 +66,8 @@ void unselect_all () { _display.get_selection()->unselect_all (); } + + void delete_unused_regions(); XMLNode& get_state () const; void set_state (const XMLNode &); @@ -131,6 +133,7 @@ bool key_press (GdkEventKey *); bool button_press (GdkEventButton *); + void show_context_menu (int button, int time); int sorter (Gtk::TreeModel::iterator, Gtk::TreeModel::iterator); @@ -139,6 +142,7 @@ void add_region (boost::shared_ptr<ARDOUR::Region>); void add_regions (std::vector<boost::shared_ptr<ARDOUR::Region> > & ); + void populate_row (boost::shared_ptr<ARDOUR::Region>, Gtk::TreeModel::Row const &); void populate_row_used (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used); void populate_row_position (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used); @@ -155,7 +159,9 @@ void populate_row_source (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row); void update_row (boost::shared_ptr<ARDOUR::Region>); + bool update_subrows (boost::shared_ptr<ARDOUR::Region>, Gtk::TreeModel::Row const &, int); + void update_all_rows (); void update_all_subrows (Gtk::TreeModel::Row const &, int); void insert_into_tmp_regionlist (boost::shared_ptr<ARDOUR::Region>); @@ -169,22 +175,30 @@ Glib::RefPtr<Gtk::Action> hide_action () const; Glib::RefPtr<Gtk::Action> show_action () const; + Glib::RefPtr<Gtk::Action> delete_unused_regions_action() const; Glib::RefPtr<Gtk::ToggleAction> toggle_full_action () const; Glib::RefPtr<Gtk::ToggleAction> toggle_show_auto_regions_action () const; Gtk::Menu* _menu; Gtk::ScrolledWindow _scroller; Gtk::Frame _frame; + Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Region> > _display; + Glib::RefPtr<Gtk::TreeStore> _model; + bool _show_automatic_regions; + bool ignore_region_list_selection_change; + bool ignore_selected_region_change; + bool _no_redisplay; + Editing::RegionListSortType _sort_type; - bool _no_redisplay; + std::list<boost::shared_ptr<ARDOUR::Region> > tmp_region_list; + PBD::ScopedConnection region_property_connection; PBD::ScopedConnection check_new_region_connection; - bool ignore_region_list_selection_change; - bool ignore_selected_region_change; + bool expanded; }; Index: libs/ardour/ardour/session.h =================================================================== --- libs/ardour/ardour/session.h (revision 7841) +++ libs/ardour/ardour/session.h (working copy) @@ -512,6 +512,7 @@ void add_source (boost::shared_ptr<Source>); void remove_source (boost::weak_ptr<Source>); + void cleanup_regions(); int cleanup_sources (CleanupReport&); int cleanup_trash_sources (CleanupReport&); Index: libs/ardour/ardour/region_factory.h =================================================================== --- libs/ardour/ardour/region_factory.h (revision 7841) +++ libs/ardour/ardour/region_factory.h (working copy) @@ -56,7 +56,7 @@ static PBD::Signal1<void,boost::shared_ptr<Region> > CheckNewRegion; /** create a "pure copy" of Region @param other */ - static boost::shared_ptr<Region> create (boost::shared_ptr<const Region> other, bool announce = false); + static boost::shared_ptr<Region> create (boost::shared_ptr<const Region> other, bool announce = false, bool automatic = false); /** create a region from a single Source */ static boost::shared_ptr<Region> create (boost::shared_ptr<Source>, Index: libs/ardour/session_state.cc =================================================================== --- libs/ardour/session_state.cc (revision 7841) +++ libs/ardour/session_state.cc (working copy) @@ -1082,11 +1082,15 @@ child = node->add_child ("Regions"); if (full_state) { + Glib::Mutex::Lock rl (region_lock); const RegionFactory::RegionMap& region_map (RegionFactory::all_regions()); - for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) { - boost::shared_ptr<Region> r = i->second; - /* only store regions not attached to playlists */ + + for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) { + + boost::shared_ptr<Region> r = i->second; + + /* only store regions not attached to playlists */ if (r->playlist() == 0) { child->add_child_nocopy (r->state ()); } @@ -2486,6 +2490,28 @@ 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<AudioRegion> audioregion = boost::dynamic_pointer_cast<AudioRegion>( i->second); + uint32_t used = playlists->region_use_count (audioregion); + + if (used == 0){ + RegionFactory::map_remove(i->second); + } + } + + /* dump the history list */ + _history.clear (); + + save_state (""); +} + + int Session::cleanup_sources (CleanupReport& rep) { Index: libs/ardour/region_factory.cc =================================================================== --- libs/ardour/region_factory.cc (revision 7841) +++ libs/ardour/region_factory.cc (working copy) @@ -45,7 +45,7 @@ std::map<std::string, uint32_t> RegionFactory::region_name_map; boost::shared_ptr<Region> -RegionFactory::create (boost::shared_ptr<const Region> region, bool announce) +RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, bool automatic) { boost::shared_ptr<Region> ret; boost::shared_ptr<const AudioRegion> ar; @@ -73,10 +73,15 @@ if (ret) { ret->set_name (new_region_name(ret->name())); - map_add (ret); + + if (!automatic){ + map_add (ret); + } + else { + ret->set_automatic(true); + } /* pure copy constructor - no property list */ - /* pure copy constructor - no CheckNewRegion emitted */ if (announce) { CheckNewRegion (ret); } @@ -317,8 +322,6 @@ i = tmp; } - - } boost::shared_ptr<Region> Index: libs/ardour/audio_diskstream.cc =================================================================== --- libs/ardour/audio_diskstream.cc (revision 7841) +++ libs/ardour/audio_diskstream.cc (working copy) @@ -78,7 +78,6 @@ , channels (new ChannelList) { /* prevent any write sources from being created */ - in_set_state = true; use_new_playlist (); in_set_state = false; @@ -1443,34 +1442,6 @@ string whole_file_region_name; whole_file_region_name = region_name_from_path (c->front()->write_source->name(), true); - /* Register a new region with the Session that - describes the entire source. Do this first - so that any sub-regions will obviously be - children of this one (later!) - */ - - try { - PropertyList plist; - - plist.add (Properties::start, c->front()->write_source->last_capture_start_frame()); - plist.add (Properties::length, total_capture); - plist.add (Properties::name, whole_file_region_name); - boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist)); - rx->set_automatic (true); - rx->set_whole_file (true); - - region = boost::dynamic_pointer_cast<AudioRegion> (rx); - region->special_set_position (capture_info.front()->start); - } - - - catch (failed_constructor& err) { - error << string_compose(_("%1: could not create region for complete audio file"), _name) << endmsg; - /* XXX what now? */ - } - - _last_capture_sources.insert (_last_capture_sources.end(), srcs.begin(), srcs.end()); - // cerr << _name << ": there are " << capture_info.size() << " capture_info records\n"; _playlist->clear_changes (); @@ -1491,7 +1462,7 @@ plist.add (Properties::start, buffer_position); plist.add (Properties::length, (*ci)->frames); plist.add (Properties::name, region_name); - + boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist)); region = boost::dynamic_pointer_cast<AudioRegion> (rx); } @@ -2217,7 +2188,7 @@ region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (pending_sources, plist)); - region->set_automatic (true); + //region->set_automatic (true); region->set_whole_file (true); region->special_set_position (0); } |
2010-11-01 00:11
|
remove-unused-regions-function-2.patch (27,542 bytes)
Index: gtk2_ardour/editor_regions.cc =================================================================== --- gtk2_ardour/editor_regions.cc (revision 7945) +++ gtk2_ardour/editor_regions.cc (working copy) @@ -260,6 +260,7 @@ } if (region->hidden()) { + TreeModel::iterator iter = _model->get_iter ("0"); TreeModel::Row parent; TreeModel::Row child; @@ -282,38 +283,58 @@ } row = *(_model->append (parent.children())); - } else if (region->whole_file()) { + } else if (!_show_automatic_regions){ + row = row = *(_model->append()); + } 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<Region> rr = (*i)[_columns.region]; + boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion>(rr); - if (rr && region->region_list_equivalent (rr)) { - return; + if (r && region->source_equivalent (r) && r->automatic()) { + + row = *(_model->append ((*i).children())); + found_parent = true; + + break; } + + TreeModel::iterator ii; + TreeModel::Children subrows = (*i).children(); + + for (ii = subrows.begin(); ii != subrows.end(); ++ii) { + boost::shared_ptr<Region> rrr = (*ii)[_columns.region]; + + if (region->region_list_equivalent (rrr)) { + return; + + } + } } - row = *(_model->append()); + if (!found_parent) { - if (missing_source) { - c.set_rgb(65535,0,0); // FIXME: error color from style + row = *(_model->append()); - } else if (region->automatic()){ - c.set_rgb(0,65535,0); // FIXME: error color from style + if (missing_source) { + c.set_rgb(65535,0,0); // FIXME: error color from style - } else { - set_color(c, rgba_from_style ("RegionListWholeFile", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL, false )); + } else { + c.set_rgb(0,65535,0); // FIXME: error color from style - } + } - row[_columns.color_] = c; + row[_columns.color_] = c; - if (region->source()->name()[0] == '/') { // external file + if (region->source()->name()[0] == '/') { // external file - if (region->whole_file()) { - boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(region->source()); str = ".../"; @@ -322,86 +343,41 @@ } else { str += region->source()->name(); } - } else { - str = region->name(); + str += region_name_from_path (region->source()->name(), true); } - } else { - str = region->name(); - } + if (region->n_channels() > 1) { + std::stringstream foo; + foo << region->n_channels (); + str += " ["; + str += foo.str(); + str += "]"; - if (region->n_channels() > 1) { - std::stringstream foo; - foo << region->n_channels (); - str += " ["; - str += foo.str(); - str += "]"; - } - - row[_columns.name] = str; - row[_columns.region] = region; - row[_columns.property_toggles_visible] = false; - - if (missing_source) { - row[_columns.path] = _("(MISSING) ") + region->source()->name(); - - } else { - boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource>(region->source()); - if (fs) { - row[_columns.path] = fs->path(); - } else { - row[_columns.path] = region->source()->name(); - } - } - - if (region->automatic()) { - 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<Region> r = (*i)[_columns.region]; - - if (r && r->whole_file()) { - - if (region->source_equivalent (r)) { - found_parent = true; - } } - - TreeModel::iterator ii; - TreeModel::Children subrows = (*i).children(); + + /* Create an automatic region to serve as the parent node in the tree */ + boost::shared_ptr<Region> r = RegionFactory::create (region, false, true); + + row[_columns.name] = str; + row[_columns.region] = r; + row[_columns.property_toggles_visible] = false; - for (ii = subrows.begin(); ii != subrows.end(); ++ii) { - boost::shared_ptr<Region> rr = (*ii)[_columns.region]; + if (missing_source) { + row[_columns.path] = _("(MISSING) ") + region->source()->name(); - if (region->region_list_equivalent (rr)) { - return; - } + } else { + row[_columns.path] = region->source()->name(); } - - if (found_parent) { - row = *(_model->append ((*i).children())); - break; - } + + /* Now add the region to the parent row just created */ + row = *(_model->append (row.children())); } - - if (!found_parent) { - row = *(_model->append()); - } - - row[_columns.property_toggles_visible] = true; } row[_columns.region] = region; + row[_columns.name] = region->name(); + row[_columns.property_toggles_visible] = true; populate_row(region, (*row)); } @@ -438,66 +414,93 @@ } } - 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 (); + TreeModel::Row row; + while (i != rows.end ()) { - + TreeModel::Children children = (*i)->children (); - TreeModel::iterator j = children.begin (); - - while (j != children.end()) { + + if (_show_automatic_regions){ - boost::shared_ptr<Region> c = (*j)[_columns.region]; - + // Get the child nodes and match the region against the children + + TreeModel::iterator j = children.begin (); + + while (j != children.end()) { + + boost::shared_ptr<Region> c = (*j)[_columns.region]; + + if (c == r) { + row = *j; + break; + } + + ++j; + } + } + else { + boost::shared_ptr<Region> c = (*i)[_columns.region]; + if (c == r) { - last_row = TreeRowReference(_model, TreePath(j)); - break; + row = *i; } - ++j; } - - if (j != children.end()) { - + + // Row found, update the view + if (row) { + + last_row = TreeRowReference (_model, TreePath(row)); + boost::shared_ptr<AudioRegion> audioregion = boost::dynamic_pointer_cast<AudioRegion>(r); uint32_t used = _editor->get_regionview_count_from_region_list (r); if (what_changed.contains (ARDOUR::Properties::name)) { - populate_row_name (r, *j); + populate_row_name (r, *row); } + if (what_changed.contains (ARDOUR::Properties::position)) { - populate_row_position (r, *j, used); - populate_row_end (r, *j, used); + populate_row_position (r, *row, used); + populate_row_end (r, *row, used); } + if (what_changed.contains (ARDOUR::Properties::length)) { - populate_row_end (r, *j, used); - populate_row_length (r, *j); + populate_row_end (r, *row, used); + populate_row_length (r, *row); } + if (what_changed.contains (ARDOUR::Properties::start)) { - populate_row_start (r, *j, used); - populate_row_length (r, *j); + populate_row_start (r, *row, used); + populate_row_length (r, *row); } + if (what_changed.contains (ARDOUR::Properties::locked)) { - populate_row_locked (r, *j, used); + populate_row_locked (r, *row, used); } + if (what_changed.contains (ARDOUR::Properties::position_lock_style)) { - populate_row_glued (r, *j, used); + populate_row_glued (r, *row, used); } + if (what_changed.contains (ARDOUR::Properties::muted)) { - populate_row_muted (r, *j, used); + populate_row_muted (r, *row, used); } + if (what_changed.contains (ARDOUR::Properties::opaque)) { - populate_row_opaque (r, *j, used); + populate_row_opaque (r, *row, used); } + if (what_changed.contains (ARDOUR::Properties::fade_in)) { - populate_row_fade_in (r, *j, used, audioregion); + populate_row_fade_in (r, *row, used, audioregion); } + if (what_changed.contains (ARDOUR::Properties::fade_out)) { - populate_row_fade_out (r, *j, used, audioregion); + populate_row_fade_out (r, *row, used, audioregion); } break; @@ -647,6 +650,7 @@ 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); } @@ -654,6 +658,7 @@ for (list<boost::shared_ptr<Region> >::iterator r = tmp_region_list.begin(); r != tmp_region_list.end(); ++r) { add_region (*r); } + tmp_region_list.clear(); _display.set_model (_model); @@ -1050,7 +1055,15 @@ } } + void +EditorRegions::delete_unused_regions () +{ + _session->cleanup_regions(); + redisplay(); +} + +void EditorRegions::toggle_show_auto_regions () { _show_automatic_regions = toggle_show_auto_regions_action()->get_active(); @@ -1094,9 +1107,12 @@ bool have_hidden = false; TreeView::Selection::ListHandle_Path rows = _display.get_selection()->get_selected_rows (); + for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) { + TreeIter t = _model->get_iter (*i); boost::shared_ptr<Region> r = (*t)[_columns.region]; + if (r) { if (r->hidden ()) { have_hidden = true; @@ -1519,6 +1535,7 @@ } XMLProperty const * p = node.property (X_("sort-type")); + if (p) { Editing::RegionListSortType const t = static_cast<Editing::RegionListSortType> (string_2_enum (p->value(), _sort_type)); if (_sort_type != t) { @@ -1530,6 +1547,7 @@ } p = node.property (X_("sort-ascending")); + if (p) { bool const yn = string_is_affirmative (p->value ()); SortType old_sort_type; @@ -1551,6 +1569,7 @@ } p = node.property (X_("show-all")); + if (p) { bool const yn = string_is_affirmative (p->value ()); if (expanded != yn) { @@ -1561,7 +1580,9 @@ } 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; @@ -1637,6 +1658,12 @@ return ActionManager::get_action (X_("RegionList"), X_("rlShow")); } +RefPtr<Action> +EditorRegions::delete_unused_regions_action () const +{ + return ActionManager::get_action (X_("RegionList"), X_("removeUnusedRegions")); +} + RefPtr<ToggleAction> EditorRegions::toggle_full_action () const { Index: gtk2_ardour/ardour.menus.in =================================================================== --- gtk2_ardour/ardour.menus.in (revision 7945) +++ gtk2_ardour/ardour.menus.in (working copy) @@ -514,7 +514,7 @@ <menuitem action='rlAudition'/> <menuitem action='rlHide'/> <menuitem action='rlShow'/> - <separator/> + <separator/> <menuitem action='rlShowAll'/> <menuitem action='rlShowAuto'/> <menu name='Sort' action='RegionListSort'> @@ -533,6 +533,8 @@ <menuitem action='SortBySourceFilesystem'/> </menu> <separator/> - <menuitem action='addExternalAudioToRegionList'/> + <menuitem action='addExternalAudioToRegionList'/> + <separator/> + <menuitem action='removeUnusedRegions'/> </popup> </ui> Index: gtk2_ardour/editor_drag.cc =================================================================== --- gtk2_ardour/editor_drag.cc (revision 7945) +++ gtk2_ardour/editor_drag.cc (working copy) @@ -532,6 +532,7 @@ /* Bail early if we're not over a track */ RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv.first); + if (!rtv || !rtv->is_track()) { _editor->hide_verbose_canvas_cursor (); return; @@ -599,7 +600,6 @@ iy1 += _editor->get_trackview_group_vertical_offset (); // hide any dependent views - rv->get_time_axis_view().hide_dependent_views (*rv); /* @@ -625,18 +625,21 @@ tracks. */ int this_delta_layer = delta_layer; + if (delta_time_axis_view != 0) { this_delta_layer = - i->layer; } /* Move this region to layer 0 on its old track */ StreamView* lv = _time_axis_views[i->time_axis_view]->view (); + if (lv->layer_display() == Stacked) { y_delta -= (lv->layers() - i->layer - 1) * lv->child_height (); } /* Now move it to its right layer on the current track */ StreamView* cv = _time_axis_views[i->time_axis_view + delta_time_axis_view]->view (); + if (cv->layer_display() == Stacked) { y_delta += (cv->layers() - (i->layer + this_delta_layer) - 1) * cv->child_height (); } @@ -702,6 +705,7 @@ region_copy->set_position (original->position(), this); RegionView* nrv; + if (arv) { boost::shared_ptr<AudioRegion> audioregion_copy = boost::dynamic_pointer_cast<AudioRegion>(region_copy); @@ -1604,11 +1608,14 @@ _have_transaction = true; for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) { + RegionView* rv = i->view; rv->fake_set_opaque(false); rv->enable_display (false); rv->region()->clear_changes (); + rv->region()->suspend_property_changes (); + AudioRegionView* const arv = dynamic_cast<AudioRegionView*> (rv); if (arv){ @@ -1654,6 +1661,7 @@ framecnt_t frame_delta = 0; bool left_direction = false; + if (last_pointer_frame() > pf) { left_direction = true; } @@ -1696,14 +1704,17 @@ } else { for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) { + _editor->thaw_region_after_trim (*i->view); i->view->enable_display (true); i->view->fake_set_opaque (true); + if (_have_transaction) { _editor->session()->add_command (new StatefulDiffCommand (i->view->region())); } } } + for (set<boost::shared_ptr<Playlist> >::iterator p = _editor->motion_frozen_playlists.begin(); p != _editor->motion_frozen_playlists.end(); ++p) { (*p)->thaw (); } Index: gtk2_ardour/editor_actions.cc =================================================================== --- gtk2_ardour/editor_actions.cc (revision 7945) +++ gtk2_ardour/editor_actions.cc (working copy) @@ -801,13 +801,16 @@ 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"), @@ -834,6 +837,7 @@ 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 */ @@ -917,6 +921,7 @@ } Glib::RefPtr<Action> act = ActionManager::get_action (X_("Rulers"), action); + if (act) { Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act); update_ruler_visibility (); Index: gtk2_ardour/editor_regions.h =================================================================== --- gtk2_ardour/editor_regions.h (revision 7945) +++ gtk2_ardour/editor_regions.h (working copy) @@ -66,6 +66,8 @@ void unselect_all () { _display.get_selection()->unselect_all (); } + + void delete_unused_regions(); XMLNode& get_state () const; void set_state (const XMLNode &); @@ -137,10 +139,12 @@ 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); @@ -149,6 +153,7 @@ void add_region (boost::shared_ptr<ARDOUR::Region>); void add_regions (std::vector<boost::shared_ptr<ARDOUR::Region> > & ); + void populate_row (boost::shared_ptr<ARDOUR::Region>, Gtk::TreeModel::Row const &); void populate_row_used (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used); void populate_row_position (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used); @@ -166,7 +171,9 @@ void populate_row_source (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row); void update_row (boost::shared_ptr<ARDOUR::Region>); + bool update_subrows (boost::shared_ptr<ARDOUR::Region>, Gtk::TreeModel::Row const &, int); + void update_all_rows (); void update_all_subrows (Gtk::TreeModel::Row const &, int); void insert_into_tmp_regionlist (boost::shared_ptr<ARDOUR::Region>); @@ -180,22 +187,30 @@ Glib::RefPtr<Gtk::Action> hide_action () const; Glib::RefPtr<Gtk::Action> show_action () const; + Glib::RefPtr<Gtk::Action> delete_unused_regions_action() const; Glib::RefPtr<Gtk::ToggleAction> toggle_full_action () const; Glib::RefPtr<Gtk::ToggleAction> toggle_show_auto_regions_action () const; Gtk::Menu* _menu; Gtk::ScrolledWindow _scroller; Gtk::Frame _frame; + Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Region> > _display; + Glib::RefPtr<Gtk::TreeStore> _model; + bool _show_automatic_regions; + bool ignore_region_list_selection_change; + bool ignore_selected_region_change; + bool _no_redisplay; + Editing::RegionListSortType _sort_type; - bool _no_redisplay; + std::list<boost::shared_ptr<ARDOUR::Region> > tmp_region_list; + PBD::ScopedConnection region_property_connection; PBD::ScopedConnection check_new_region_connection; - bool ignore_region_list_selection_change; - bool ignore_selected_region_change; + bool expanded; }; Index: libs/ardour/ardour/session.h =================================================================== --- libs/ardour/ardour/session.h (revision 7945) +++ libs/ardour/ardour/session.h (working copy) @@ -512,6 +512,7 @@ void add_source (boost::shared_ptr<Source>); void remove_source (boost::weak_ptr<Source>); + void cleanup_regions(); int cleanup_sources (CleanupReport&); int cleanup_trash_sources (CleanupReport&); Index: libs/ardour/ardour/region_factory.h =================================================================== --- libs/ardour/ardour/region_factory.h (revision 7945) +++ libs/ardour/ardour/region_factory.h (working copy) @@ -56,7 +56,7 @@ static PBD::Signal1<void,boost::shared_ptr<Region> > CheckNewRegion; /** create a "pure copy" of Region @param other */ - static boost::shared_ptr<Region> create (boost::shared_ptr<const Region> other, bool announce = false); + static boost::shared_ptr<Region> create (boost::shared_ptr<const Region> other, bool announce = false, bool automatic = false); /** create a region from a single Source */ static boost::shared_ptr<Region> create (boost::shared_ptr<Source>, Index: libs/ardour/session_state.cc =================================================================== --- libs/ardour/session_state.cc (revision 7945) +++ libs/ardour/session_state.cc (working copy) @@ -1082,11 +1082,15 @@ child = node->add_child ("Regions"); if (full_state) { + Glib::Mutex::Lock rl (region_lock); const RegionFactory::RegionMap& region_map (RegionFactory::all_regions()); - for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) { - boost::shared_ptr<Region> r = i->second; - /* only store regions not attached to playlists */ + + for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) { + + boost::shared_ptr<Region> r = i->second; + + /* only store regions not attached to playlists */ if (r->playlist() == 0) { child->add_child_nocopy (r->state ()); } @@ -2486,6 +2490,28 @@ 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<AudioRegion> audioregion = boost::dynamic_pointer_cast<AudioRegion>( i->second); + uint32_t used = playlists->region_use_count (audioregion); + + if (used == 0){ + RegionFactory::map_remove(i->second); + } + } + + /* dump the history list */ + _history.clear (); + + save_state (""); +} + + int Session::cleanup_sources (CleanupReport& rep) { Index: libs/ardour/region_factory.cc =================================================================== --- libs/ardour/region_factory.cc (revision 7945) +++ libs/ardour/region_factory.cc (working copy) @@ -45,7 +45,7 @@ std::map<std::string, uint32_t> RegionFactory::region_name_map; boost::shared_ptr<Region> -RegionFactory::create (boost::shared_ptr<const Region> region, bool announce) +RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, bool automatic) { boost::shared_ptr<Region> ret; boost::shared_ptr<const AudioRegion> ar; @@ -73,10 +73,15 @@ if (ret) { ret->set_name (new_region_name(ret->name())); - map_add (ret); + + if (!automatic){ + map_add (ret); + } + else { + ret->set_automatic(true); + } /* pure copy constructor - no property list */ - /* pure copy constructor - no CheckNewRegion emitted */ if (announce) { CheckNewRegion (ret); } @@ -317,8 +322,6 @@ i = tmp; } - - } boost::shared_ptr<Region> Index: libs/ardour/audio_diskstream.cc =================================================================== --- libs/ardour/audio_diskstream.cc (revision 7945) +++ libs/ardour/audio_diskstream.cc (working copy) @@ -78,7 +78,6 @@ , channels (new ChannelList) { /* prevent any write sources from being created */ - in_set_state = true; use_new_playlist (); in_set_state = false; @@ -1445,34 +1444,6 @@ string whole_file_region_name; whole_file_region_name = region_name_from_path (c->front()->write_source->name(), true); - /* Register a new region with the Session that - describes the entire source. Do this first - so that any sub-regions will obviously be - children of this one (later!) - */ - - try { - PropertyList plist; - - plist.add (Properties::start, c->front()->write_source->last_capture_start_frame()); - plist.add (Properties::length, total_capture); - plist.add (Properties::name, whole_file_region_name); - boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist)); - rx->set_automatic (true); - rx->set_whole_file (true); - - region = boost::dynamic_pointer_cast<AudioRegion> (rx); - region->special_set_position (capture_info.front()->start); - } - - - catch (failed_constructor& err) { - error << string_compose(_("%1: could not create region for complete audio file"), _name) << endmsg; - /* XXX what now? */ - } - - _last_capture_sources.insert (_last_capture_sources.end(), srcs.begin(), srcs.end()); - // cerr << _name << ": there are " << capture_info.size() << " capture_info records\n"; _playlist->clear_changes (); @@ -1493,7 +1464,7 @@ plist.add (Properties::start, buffer_position); plist.add (Properties::length, (*ci)->frames); plist.add (Properties::name, region_name); - + boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist)); region = boost::dynamic_pointer_cast<AudioRegion> (rx); } @@ -2219,7 +2190,6 @@ region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (pending_sources, plist)); - region->set_automatic (true); region->set_whole_file (true); region->special_set_position (0); } |
|
Added an updated version of this patch. This one includes a fix to update region list entries when not displaying Automatic Regions. |
|
When I go home... I'll try the patch out (after updating to 7945.. or newer) and see how it works. |
|
I checked out 3.0 -r 7945 and tried to apply the patch and got lots of rejects |
|
Did you apply remove-unused-regions-function-2.patch? It applies against a clean pull for me. |
|
DUH... wrong patch level ... -p1 (I am used to doing patch one up .. not from inside the src (root) directory ... it works applies both to head and 7945 and seems to work.. (not extensively tested) and I like the remove unused menu within the 2nd-click context of the region list! |
|
This feature has been added to Ardour 3 as part of a patch for region list speed ups. It only caters for Audio regions for now. |
Date Modified | Username | Field | Change |
---|---|---|---|
2010-09-25 21:44 | lincoln | New Issue | |
2010-09-25 21:44 | lincoln | File Added: remove-unused-regions-function.patch | |
2010-09-27 18:59 | cth103 | cost | => 0.00 |
2010-09-27 18:59 | cth103 | Target Version | => 3.X |
2010-11-01 00:11 | lincoln | File Added: remove-unused-regions-function-2.patch | |
2010-11-01 00:12 | lincoln | Note Added: 0009334 | |
2010-11-03 14:56 | dx9s | Note Added: 0009337 | |
2010-11-03 23:54 | dx9s | Note Added: 0009338 | |
2010-11-04 00:03 | lincoln | Note Added: 0009339 | |
2010-11-04 01:26 | dx9s | Note Added: 0009341 | |
2010-12-22 01:08 | cth103 | Relationship added | related to 0003619 |
2011-02-23 07:34 | lincoln | Note Added: 0010176 |