View Issue Details

IDProjectCategoryView StatusLast Update
0003715ardourfeaturespublic2020-04-19 20:15
Reporterlincoln Assigned Tocth103  
PrioritynormalSeverityfeatureReproducibilityN/A
Status closedResolutionfixed 
Target Version3.0-beta1 
Summary0003715: Fixes for rhythm ferret
DescriptionThe attached patch adds some fixes and enchantments for rhythm ferret as follows:

- Restore operation on an active group when splitting regions
- Auto select newly created regions that are created after the split operation
- Remove the unused tempo map function and replace it with snap regions to grid.

A second patch addresses an issue with nested transactions. Without this the split operation crashes Ardour.

The patch also contains a new function to return only selected regions (disregard entered tracks)
TagsNo tags attached.

Activities

2011-01-16 00:08

 

rhythm-ferret-fixes.patch (16,702 bytes)   
Index: gtk2_ardour/public_editor.h
===================================================================
--- gtk2_ardour/public_editor.h	(revision 8514)
+++ gtk2_ardour/public_editor.h	(working copy)
@@ -268,7 +268,7 @@
 	virtual void restore_editing_space () = 0;
 	virtual framepos_t get_preferred_edit_position (bool ignore_playhead = false) = 0;
 	virtual void toggle_meter_updating() = 0;
-	virtual void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret) = 0;
+	virtual void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false) = 0;
 	virtual void mouse_add_new_marker (framepos_t where, bool is_cd=false, bool is_xrun=false) = 0;
 	virtual void foreach_time_axis_view (sigc::slot<void,TimeAxisView&>) = 0;
 	virtual void add_to_idle_resize (TimeAxisView*, int32_t) = 0;
Index: gtk2_ardour/editor_ops.cc
===================================================================
--- gtk2_ardour/editor_ops.cc	(revision 8514)
+++ gtk2_ardour/editor_ops.cc	(working copy)
@@ -2862,7 +2862,9 @@
 {
 	vector<PlaylistState> playlists;
 
-	RegionSelection rs = get_regions_from_selection_and_entered ();
+	RegionSelection rs;
+	
+	rs = get_regions_from_selection_and_entered();
 
 	if (!_session || rs.empty()) {
 		return;
@@ -5738,11 +5740,13 @@
 }
 
 void
-Editor::split_region_at_points (boost::shared_ptr<Region> r, AnalysisFeatureList& positions, bool can_ferret)
+Editor::split_region_at_points (boost::shared_ptr<Region> r, AnalysisFeatureList& positions, bool can_ferret, bool select_new)
 {
 	bool use_rhythmic_rodent = false;
-
+	
 	boost::shared_ptr<Playlist> pl = r->playlist();
+	
+	list<boost::shared_ptr<Region> > new_regions;
 
 	if (!pl) {
 		return;
@@ -5753,7 +5757,7 @@
 	}
 
 
-	if (positions.size() > 20) {
+	if (positions.size() > 20 && can_ferret) {
 		std::string msgstr = string_compose (_("You are about to split\n%1\ninto %2 pieces.\nThis could take a long time."), r->name(), positions.size() + 1);
 		MessageDialog msg (msgstr,
 				   false,
@@ -5847,6 +5851,10 @@
 
 		boost::shared_ptr<Region> nr = RegionFactory::create (r->sources(), plist, false);
 		pl->add_region (nr, r->position() + pos);
+		
+		if (select_new){
+			new_regions.push_front(nr);
+		}
 
 		pos += len;
 		++x;
@@ -5866,11 +5874,21 @@
 
 	boost::shared_ptr<Region> nr = RegionFactory::create (r->sources(), plist, false);
 	pl->add_region (nr, r->position() + pos);
+	
+	if (select_new){
+		new_regions.push_front(nr);
+	}
 
-	
 	pl->thaw ();
 
 	_session->add_command (new StatefulDiffCommand (pl));
+	
+	if (select_new){
+
+		for (list<boost::shared_ptr<Region> >::iterator i = new_regions.begin(); i != new_regions.end(); ++i){
+			set_selected_regionview_from_region_list ((*i), Selection::Add);
+		}
+	}
 }
 
 void
@@ -5953,7 +5971,7 @@
 	SpinButton spin_crossfade (1, 0);
 	spin_crossfade.set_range (0, 15);
 	spin_crossfade.set_increments (1, 1);
-	spin_crossfade.set_value (3);
+	spin_crossfade.set_value (5);
 	table.attach (spin_crossfade, 1, 2, 0, 1);
 
 	table.attach (*manage (new Label (_("ms"))), 2, 3, 0, 1);
@@ -5963,9 +5981,9 @@
 	table.attach (*l, 0, 1, 1, 2);
 	
 	SpinButton spin_pullback (1, 0);
-	spin_pullback.set_range (0, 15);
+	spin_pullback.set_range (0, 100);
 	spin_pullback.set_increments (1, 1);
-	spin_pullback.set_value (5);
+	spin_pullback.set_value(30);
 	table.attach (spin_pullback, 1, 2, 1, 2);
 
 	table.attach (*manage (new Label (_("ms"))), 2, 3, 1, 2);
@@ -6200,9 +6218,9 @@
 		msg.run ();
 		return;
 	}
-                
+
 	if (ntracks + nbusses == 0) {
- 		return;
+		return;
 	}
 
 	if (ntracks > 1) {
Index: gtk2_ardour/rhythm_ferret.h
===================================================================
--- gtk2_ardour/rhythm_ferret.h	(revision 8514)
+++ gtk2_ardour/rhythm_ferret.h	(working copy)
@@ -33,7 +33,7 @@
 
 	enum Action {
 		SplitRegion,
-		DefineTempoMap,
+		SnapRegionsToGrid,
 		ConformRegion
 	};
 
Index: gtk2_ardour/editor.cc
===================================================================
--- gtk2_ardour/editor.cc	(revision 8514)
+++ gtk2_ardour/editor.cc	(working copy)
@@ -395,18 +395,21 @@
 	bbt_label.set_padding (5,0);
 	bbt_label.hide ();
 	bbt_label.set_no_show_all();
+	
 	minsec_label.set_name ("EditorTimeButton");
 	minsec_label.set_size_request (-1, (int)timebar_height);
 	minsec_label.set_alignment (1.0, 0.5);
 	minsec_label.set_padding (5,0);
 	minsec_label.hide ();
 	minsec_label.set_no_show_all();
+	
 	timecode_label.set_name ("EditorTimeButton");
 	timecode_label.set_size_request (-1, (int)timebar_height);
 	timecode_label.set_alignment (1.0, 0.5);
 	timecode_label.set_padding (5,0);
 	timecode_label.hide ();
 	timecode_label.set_no_show_all();
+	
 	frame_label.set_name ("EditorTimeButton");
 	frame_label.set_size_request (-1, (int)timebar_height);
 	frame_label.set_alignment (1.0, 0.5);
@@ -420,30 +423,35 @@
 	tempo_label.set_padding (5,0);
 	tempo_label.hide();
 	tempo_label.set_no_show_all();
+	
 	meter_label.set_name ("EditorTimeButton");
 	meter_label.set_size_request (-1, (int)timebar_height);
 	meter_label.set_alignment (1.0, 0.5);
 	meter_label.set_padding (5,0);
 	meter_label.hide();
 	meter_label.set_no_show_all();
+	
 	mark_label.set_name ("EditorTimeButton");
 	mark_label.set_size_request (-1, (int)timebar_height);
 	mark_label.set_alignment (1.0, 0.5);
 	mark_label.set_padding (5,0);
 	mark_label.hide();
 	mark_label.set_no_show_all();
+	
 	cd_mark_label.set_name ("EditorTimeButton");
 	cd_mark_label.set_size_request (-1, (int)timebar_height);
 	cd_mark_label.set_alignment (1.0, 0.5);
 	cd_mark_label.set_padding (5,0);
 	cd_mark_label.hide();
 	cd_mark_label.set_no_show_all();
+	
 	range_mark_label.set_name ("EditorTimeButton");
 	range_mark_label.set_size_request (-1, (int)timebar_height);
 	range_mark_label.set_alignment (1.0, 0.5);
 	range_mark_label.set_padding (5,0);
 	range_mark_label.hide();
 	range_mark_label.set_no_show_all();
+	
 	transport_mark_label.set_name ("EditorTimeButton");
 	transport_mark_label.set_size_request (-1, (int)timebar_height);
 	transport_mark_label.set_alignment (1.0, 0.5);
@@ -453,11 +461,14 @@
 
 	initialize_rulers ();
 	initialize_canvas ();
+	
 	_summary = new EditorSummary (this);
 
 	selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
 	selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
+	
 	editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
+	
 	selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
 	selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
 
@@ -484,8 +495,10 @@
 	ArdourCanvas::Canvas* time_pad = manage(new ArdourCanvas::Canvas());
 	ArdourCanvas::SimpleLine* pad_line_1 = manage(new ArdourCanvas::SimpleLine(*time_pad->root(),
 			0.0, 1.0, 100.0, 1.0));
+	
 	pad_line_1->property_color_rgba() = 0xFF0000FF;
 	pad_line_1->show();
+	
 	time_pad->show();
 
 	time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars) + 2);
@@ -558,10 +571,12 @@
 	summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
 	summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::mem_fun (*this, &Editor::horizontal_scroll_left_press)));
 	summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_left_release));
+	
 	Button* summary_arrows_left_right = manage (new Button);
 	summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
 	summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::mem_fun (*this, &Editor::horizontal_scroll_right_press)));
 	summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_right_release));
+	
 	VBox* summary_arrows_left = manage (new VBox);
 	summary_arrows_left->pack_start (*summary_arrows_left_left);
 	summary_arrows_left->pack_start (*summary_arrows_left_right);
@@ -570,16 +585,19 @@
 	summary_arrows_right_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
 	summary_arrows_right_left->signal_pressed().connect (sigc::hide_return (sigc::mem_fun (*this, &Editor::horizontal_scroll_left_press)));
 	summary_arrows_right_left->signal_released().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_left_release));
+	
 	Button* summary_arrows_right_right = manage (new Button);
 	summary_arrows_right_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
 	summary_arrows_right_right->signal_pressed().connect (sigc::hide_return (sigc::mem_fun (*this, &Editor::horizontal_scroll_right_press)));
 	summary_arrows_right_right->signal_released().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_right_release));
+	
 	VBox* summary_arrows_right = manage (new VBox);
 	summary_arrows_right->pack_start (*summary_arrows_right_left);
 	summary_arrows_right->pack_start (*summary_arrows_right_right);
 
 	Frame* summary_frame = manage (new Frame);
 	summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
+	
 	summary_frame->add (*_summary);
 	summary_frame->show ();
 
@@ -1105,9 +1123,11 @@
 	Location* loc = _session->locations()->auto_loop_location();
 	if (loc == 0) {
 		loc = new Location (*_session, 0, _session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
+		
 		if (loc->start() == loc->end()) {
 			loc->set_end (loc->start() + 1);
 		}
+		
 		_session->locations()->add (loc, false);
 		_session->set_auto_loop_location (loc);
 	} else {
@@ -1116,11 +1136,14 @@
 	}
 
 	loc = _session->locations()->auto_punch_location();
+	
 	if (loc == 0) {
 		loc = new Location (*_session, 0, _session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
+		
 		if (loc->start() == loc->end()) {
 			loc->set_end (loc->start() + 1);
 		}
+		
 		_session->locations()->add (loc, false);
 		_session->set_auto_punch_location (loc);
 	} else {
@@ -4471,7 +4494,9 @@
 	}
 
 	for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
+
 		RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
+
 		if (rtv) {
 			boost::shared_ptr<Track> tr;
 			boost::shared_ptr<Playlist> pl;
@@ -4479,7 +4504,7 @@
 			if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
 
 				Playlist::RegionList* regions = pl->regions_at (
-						(framepos_t) floor ( (double)where * tr->speed()));
+						(framepos_t) floor ( (double) where * tr->speed()));
 
 				for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
 					RegionView* rv = rtv->view()->find_view (*i);
@@ -4531,6 +4556,16 @@
 	}
 }
 
+RegionSelection
+Editor::get_regions_from_selection ()
+{
+	RegionSelection regions = selection->regions;
+	
+	regions = add_edit_group_regions_to_selection(regions);
+
+	return regions;
+}
+
 /** Get regions using the following method:
  *
  *  Make an initial region list using the selected regions, unless
@@ -4580,10 +4615,10 @@
 	for (RegionSelection::iterator i = regions.begin (); i != regions.end(); ++i) {
 		
 		RouteGroup* g = (*i)->get_time_axis_view().route_group ();
+		
 		if (g && g->is_active() && g->is_edit()) {
 			tracks.add (axis_views_from_routes (g->route_list()));
 		}
-		
 	}
 	
 	if (!tracks.empty()) {
@@ -4599,15 +4634,72 @@
 RegionSelection
 Editor::get_regions_from_selection_and_entered ()
 {
-	RegionSelection rs = selection->regions;
+	RegionSelection regions = selection->regions;
 	
-	if (rs.empty() && entered_regionview) {
-		rs.add (entered_regionview);
+	if (regions.empty() && entered_regionview) {
+		regions.add (entered_regionview);
 	}
+	
 
-	return rs;
+	regions = add_edit_group_regions_to_selection(regions);
+
+	return regions;
 }
 
+RegionSelection
+Editor::add_edit_group_regions_to_selection(RegionSelection regions){
+  
+	TrackViewList tracks;
+	
+	vector<boost::shared_ptr<Region> > equivalent_regions;
+	RegionSelection edit_group_regions;
+		
+	/* Add any other tracks that have regions that are in the same
+	   edit-activated route group as one of our regions.
+	 */
+	for (RegionSelection::iterator i = regions.begin (); i != regions.end(); ++i) {
+		
+		RouteGroup* g = (*i)->get_time_axis_view().route_group ();
+		
+		if (g && g->is_active() && g->is_edit()) {
+			/* get tracks in the group */
+			tracks.add (axis_views_from_routes (g->route_list()));
+		}
+		
+		/* iterate over the track list and get the equivalent regions for the current region */
+		for (TrackViewList::iterator tr = tracks.begin (); tr != tracks.end(); ++tr) {
+		  
+			if ( (*tr) == &(*i)->get_time_axis_view()) {
+				/* looking in same track as the original */
+				continue;
+			}
+		  
+			boost::shared_ptr<Playlist> pl;
+			
+			if ((pl = (*tr)->playlist()) != 0) {
+				pl->get_equivalent_regions ((*i)->region(), equivalent_regions);
+			}
+			
+			/* convert the regions to region views */
+			for (vector<boost::shared_ptr<Region> >::iterator r = equivalent_regions.begin(); r != equivalent_regions.end(); ++r) {
+				
+				RegionView* rv;
+				
+				if ((rv = (*tr)->view()->find_view (*r)) != 0) {
+					edit_group_regions.add (rv);
+				}
+			}
+		}
+		
+		equivalent_regions.clear();
+		tracks.clear();
+	}
+	
+	regions.merge(edit_group_regions);
+	
+	return regions;
+}
+
 void
 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions)
 {
Index: gtk2_ardour/rhythm_ferret.cc
===================================================================
--- gtk2_ardour/rhythm_ferret.cc	(revision 8514)
+++ gtk2_ardour/rhythm_ferret.cc	(working copy)
@@ -48,8 +48,8 @@
 
 static const gchar * _operation_strings[] = {
 	N_("Split region"),
-	N_("Set tempo map"),
-	N_("Conform region"),
+	N_("Snap regions"),
+	N_("Conform regions"),
 	0
 };
 
@@ -168,7 +168,7 @@
 RhythmFerret::get_action () const
 {
 	if (operation_selector.get_active_row_number() == 1) {
-		return DefineTempoMap;
+		return SnapRegionsToGrid;
 	} else if (operation_selector.get_active_row_number() == 2) {
 		return ConformRegion;
 	}
@@ -321,6 +321,9 @@
 	case SplitRegion:
 		do_split_action ();
 		break;
+	case SnapRegionsToGrid:
+		editor.snap_regions_to_grid();
+		break;
 	case ConformRegion:
 		editor.close_region_gaps();
 		break;
@@ -332,7 +335,7 @@
 void
 RhythmFerret::do_split_action ()
 {
-	RegionSelection& regions (editor.get_selection().regions);
+	RegionSelection regions = editor.get_regions_from_selection();
 	
 	if (regions.empty()) {
 		return;
@@ -348,7 +351,7 @@
 		AnalysisFeatureList features;
 		features = (*i)->region()->transients();
 		
-		merged_features.insert (merged_features.end(), features.begin(), features.end());		
+		merged_features.insert (merged_features.end(), features.begin(), features.end());
 	}
 	
 	merged_features.sort();
@@ -363,7 +366,7 @@
 
 		AnalysisFeatureList features;
 		features = (*i)->region()->transients();
-		editor.split_region_at_points ((*i)->region(), merged_features, false);
+		editor.split_region_at_points ((*i)->region(), merged_features, false, true);
 
 		/* i is invalid at this point */
 
Index: gtk2_ardour/editor.h
===================================================================
--- gtk2_ardour/editor.h	(revision 8514)
+++ gtk2_ardour/editor.h	(working copy)
@@ -1067,7 +1067,7 @@
 	void lower_region_to_bottom ();
 	void split_regions_at (framepos_t, RegionSelection&);
 	void split_region_at_transients ();
-	void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret);
+	void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false);
 	void crop_region_to_selection ();
 	void crop_region_to (framepos_t start, framepos_t end);
 	void set_sync_point (framepos_t, const RegionSelection&);
@@ -1972,8 +1972,10 @@
 	void get_regions_at (RegionSelection&, framepos_t where, const TrackViewList& ts) const;
 	void get_regions_after (RegionSelection&, framepos_t where, const TrackViewList& ts) const;
 
+	RegionSelection get_regions_from_selection ();
 	RegionSelection get_regions_from_selection_and_edit_point ();
 	RegionSelection get_regions_from_selection_and_entered ();
+	RegionSelection add_edit_group_regions_to_selection (RegionSelection regions);
 	
 	void start_updating_meters ();
 	void stop_updating_meters ();
@@ -2017,6 +2019,7 @@
 
 	Gtk::HBox _summary_hbox;
 	EditorSummary* _summary;
+
 	void region_view_added (RegionView *);
 
 	void update_canvas_now ();
rhythm-ferret-fixes.patch (16,702 bytes)   

2011-01-16 00:08

 

session-state-nested-undo-tx-fix.patch (1,346 bytes)   
Index: libs/ardour/session_state.cc
===================================================================
--- libs/ardour/session_state.cc	(revision 8514)
+++ libs/ardour/session_state.cc	(working copy)
@@ -1094,11 +1094,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 ());
                         }
@@ -2384,11 +2388,7 @@
 	UndoTransaction* trans = new UndoTransaction();
 	trans->set_name(name);
 
-	if (!_current_trans.empty()) {
-		_current_trans.top()->add_command (trans);
-	} else {
-		_current_trans.push(trans);
-	}
+	_current_trans.push(trans);
 }
 
 void

cth103

2011-01-19 17:41

administrator   ~0009948

The undo tx fix part of this patch should be unnecessary with current SVN.

cth103

2011-01-19 18:35

administrator   ~0009949

Remainder of patch applied to SVN.

system

2020-04-19 20:15

developer   ~0022372

Issue has been closed automatically, by Trigger Close Plugin.
Feel free to re-open with additional information if you think the issue is not resolved.

Issue History

Date Modified Username Field Change
2011-01-16 00:08 lincoln New Issue
2011-01-16 00:08 lincoln File Added: rhythm-ferret-fixes.patch
2011-01-16 00:08 lincoln File Added: session-state-nested-undo-tx-fix.patch
2011-01-17 19:32 cth103 cost => 0.00
2011-01-17 19:32 cth103 Target Version => 3.0-beta1
2011-01-19 17:41 cth103 Note Added: 0009948
2011-01-19 18:35 cth103 Note Added: 0009949
2011-01-19 18:35 cth103 Status new => resolved
2011-01-19 18:35 cth103 Resolution open => fixed
2011-01-19 18:35 cth103 Assigned To => cth103
2020-04-19 20:15 system Note Added: 0022372
2020-04-19 20:15 system Status resolved => closed