View Issue Details

IDProjectCategoryView StatusLast Update
0002124ardourfeaturespublic2020-04-19 20:13
Reporterhansfbaier Assigned Topaul  
PrioritynormalSeveritymajorReproducibilityN/A
Status closedResolutionfixed 
PlatformLinux Ubuntu studio gutsyOSLinuxOS Version 2.6.22-14-rt
Summary0002124: Resizing for MIDI notes implemented
DescriptionResizing works on single/multiple notes in two modes:
 -relative: note ends of all selected notes are resized by the same length (mouse-2)
 -absolute: note ends all end at mouse position (With Ctrl-mouse-2)

Beginnings are resized, if mouse2 was pressed in the first half of
the note otherwise note endings.
Steps To Reproducesee above
Additional InformationSome Screenshots: http://www.flickr.com/photos/24012642@N02/
TagsNo tags attached.

Activities

2008-03-14 23:05

 

resizing_midi_notes.diff (21,499 bytes)   
Index: gtk2_ardour/SConscript
===================================================================
--- gtk2_ardour/SConscript	(Revision 3144)
+++ gtk2_ardour/SConscript	(Arbeitskopie)
@@ -127,6 +127,7 @@
 axis_view.cc
 bundle_manager.cc
 canvas-midi-event.cc
+canvas-note.cc
 canvas-simpleline.c
 canvas-simplerect.c
 canvas-waveview.c
Index: gtk2_ardour/canvas-note.h
===================================================================
--- gtk2_ardour/canvas-note.h	(Revision 3144)
+++ gtk2_ardour/canvas-note.h	(Arbeitskopie)
@@ -1,6 +1,7 @@
 /*
-    Copyright (C) 2007 Paul Davis 
+    Copyright (C) 2007 Paul Davis
     Author: Dave Robillard
+    Author: Hans Baier
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -38,16 +39,34 @@
 		: SimpleRect(group), CanvasMidiEvent(region, this, note)
 	{
 	}
-	
+
 	double x1() { return property_x1(); }
 	double y1() { return property_y1(); }
 	double x2() { return property_x2(); }
 	double y2() { return property_y2(); }
-	
+
 	void set_outline_color(uint32_t c) { property_outline_color_rgba() = c; }
 	void set_fill_color(uint32_t c) { property_fill_color_rgba() = c; }
-	
-	bool on_event(GdkEvent* ev) { return CanvasMidiEvent::on_event(ev); }
+
+	bool on_event(GdkEvent* ev);
+
+	enum NoteEnd {
+		NOTE_ON,
+		NOTE_OFF
+	};
+
+	enum Mouse2State {
+		None,
+		RelativeResize,
+		AbsoluteResize
+	};
+
+protected:
+	Mouse2State _mouse2_state;
+
+private:
+	// single click resizing with mouse-2
+	void resize_note(double pressed_x, double event_x, double middle_point);
 };
 
 } // namespace Gnome
Index: gtk2_ardour/canvas-midi-event.cc
===================================================================
--- gtk2_ardour/canvas-midi-event.cc	(Revision 3144)
+++ gtk2_ardour/canvas-midi-event.cc	(Arbeitskopie)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2007 Paul Davis 
+    Copyright (C) 2007 Paul Davis
     Author: Dave Robillard
 
     This program is free software; you can redistribute it and/or modify
@@ -38,7 +38,7 @@
 	, _state(None)
 	, _note(note)
 	, _selected(false)
-{	
+{
 }
 
 
@@ -75,22 +75,19 @@
 
 	switch (ev->type) {
 	case GDK_KEY_PRESS:
-		cerr << "EV KEY PRESS\n";
 		if (_note && ev->key.keyval == GDK_Delete) {
-			cerr << "EV DELETE KEY\n";
 			selected(true);
 			_region.start_delta_command();
 			_region.command_remove_note(this);
 		}
 		break;
-	
+
 	case GDK_KEY_RELEASE:
-		cerr << "EV KEY RELEASE\n";
 		if (ev->key.keyval == GDK_Delete) {
 			_region.apply_command();
 		}
 		break;
-	
+
 	case GDK_ENTER_NOTIFY:
 		_region.note_entered(this);
 		_item->grab_focus();
@@ -103,13 +100,14 @@
 		break;
 
 	case GDK_BUTTON_PRESS:
-		_state = Pressed;
+		if (ev->button.button == 1) {
+			_state = Pressed;
+		}
 		return true;
 
 	case GDK_MOTION_NOTIFY:
 		event_x = ev->motion.x;
 		event_y = ev->motion.y;
-		//cerr << "MOTION @ " << event_x << ", " << event_y << endl;
 		_item->property_parent().get_value()->w2i(event_x, event_y);
 
 		switch (_state) {
@@ -135,7 +133,7 @@
 				event_x = t_x;
 				event_y = t_y;
 			}
-			
+
 			// Snap
 			event_frame = _region.midi_view()->editor.pixel_to_frame(event_x);
 			_region.midi_view()->editor.snap_to(event_frame);
@@ -143,7 +141,7 @@
 
 			dx = event_x - last_x;
 			dy = event_y - last_y;
-			
+
 			last_x = event_x;
 
 			drag_delta_x += dx;
@@ -169,7 +167,7 @@
 			break;
 		}
 		break;
-	
+
 	case GDK_BUTTON_RELEASE:
 		select_mod = (ev->motion.state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK));
 		event_x = ev->button.x;
Index: gtk2_ardour/midi_region_view.h
===================================================================
--- gtk2_ardour/midi_region_view.h	(Revision 3144)
+++ gtk2_ardour/midi_region_view.h	(Arbeitskopie)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2001-2007 Paul Davis 
+    Copyright (C) 2001-2007 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -51,16 +51,16 @@
 class MidiRegionView : public RegionView
 {
   public:
-	MidiRegionView (ArdourCanvas::Group *, 
+	MidiRegionView (ArdourCanvas::Group *,
 	                RouteTimeAxisView&,
 	                boost::shared_ptr<ARDOUR::MidiRegion>,
 	                double initial_samples_per_unit,
 	                Gdk::Color& basic_color);
 
 	~MidiRegionView ();
-	
+
 	virtual void init (Gdk::Color& basic_color, bool wfd);
-	
+
 	inline const boost::shared_ptr<ARDOUR::MidiRegion> midi_region() const
 		{ return boost::dynamic_pointer_cast<ARDOUR::MidiRegion>(_region); }
 
@@ -69,9 +69,9 @@
 
 	inline MidiStreamView* midi_stream_view() const
 		{ return midi_view()->midi_view(); }
-	
+
 	void set_y_position_and_height (double, double);
-	
+
 	void set_frame_color();
 
 	void redisplay_model();
@@ -95,7 +95,7 @@
 		if (!_delta_command)
 			_delta_command = _model->new_delta_command();
 	}
-	
+
 	void command_add_note(const boost::shared_ptr<ARDOUR::Note> note) {
 		if (_delta_command)
 			_delta_command->add(note);
@@ -121,7 +121,7 @@
 		}
 		midi_view()->midi_track()->diskstream()->playlist_modified();
 	}
-	
+
 	void   note_entered(ArdourCanvas::CanvasMidiEvent* ev);
 	void   unique_select(ArdourCanvas::CanvasMidiEvent* ev);
 	void   note_selected(ArdourCanvas::CanvasMidiEvent* ev, bool add);
@@ -131,29 +131,39 @@
 
 	void move_selection(double dx, double dy);
 	void note_dropped(ArdourCanvas::CanvasMidiEvent* ev, double dt, uint8_t dnote);
-	
+
+	void  begin_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end);
+	void update_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end, double dx, bool relative);
+	void commit_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end, double event_x, bool relative);
+
 	enum MouseState { None, Pressed, SelectTouchDragging, SelectRectDragging, AddDragging, EraseTouchDragging };
 	MouseState mouse_state() const { return _mouse_state; }
-	
+
+	struct NoteResizeData {
+		ArdourCanvas::CanvasNote  *canvas_note;
+		ArdourCanvas::SimpleRect  *resize_rect;
+		double                     current_x;
+	};
+
   protected:
 
     /* this constructor allows derived types
        to specify their visibility requirements
        to the TimeAxisViewItem parent class
     */
-    
-    MidiRegionView (ArdourCanvas::Group *, 
+
+    MidiRegionView (ArdourCanvas::Group *,
 	                RouteTimeAxisView&,
 	                boost::shared_ptr<ARDOUR::MidiRegion>,
 	                double samples_per_unit,
 	                Gdk::Color& basic_color,
 	                TimeAxisViewItem::Visibility);
-    
+
     void region_resized (ARDOUR::Change);
 
     void set_flags (XMLNode *);
     void store_flags ();
-    
+
 	void reset_width_dependent_items (double pixel_width);
 
   private:
@@ -163,10 +173,11 @@
 
 	bool canvas_event(GdkEvent* ev);
 	bool note_canvas_event(GdkEvent* ev);
-	
+
 	void clear_selection_except(ArdourCanvas::CanvasMidiEvent* ev);
 	void clear_selection() { clear_selection_except(NULL); }
 	void update_drag_selection(double last_x, double x, double last_y, double y);
+	double snap_to(double x);
 
 	double _default_note_length;
 
@@ -175,12 +186,14 @@
 	ArdourCanvas::CanvasNote**                  _active_notes;
 	ArdourCanvas::Group*                        _note_group;
 	ARDOUR::MidiModel::DeltaCommand*            _delta_command;
-		
+
 	MouseState _mouse_state;
 	int _pressed_button;
 
 	typedef std::set<ArdourCanvas::CanvasMidiEvent*> Selection;
 	Selection _selection;
+
+	std::vector<NoteResizeData *> _resize_data;
 };
 
 #endif /* __gtk_ardour_midi_region_view_h__ */
Index: gtk2_ardour/canvas-note.cc
===================================================================
--- gtk2_ardour/canvas-note.cc	(Revision 0)
+++ gtk2_ardour/canvas-note.cc	(Revision 0)
@@ -0,0 +1,91 @@
+#include "canvas-note.h"
+#include "midi_region_view.h"
+#include "public_editor.h"
+#include "ardour/note.h"
+
+using namespace ARDOUR;
+
+namespace Gnome {
+namespace Canvas {
+
+bool
+CanvasNote::on_event(GdkEvent* ev)
+{
+	double          event_x;
+	static double   middle_point, pressed_x, last_x;
+	Gdk::Cursor     cursor;
+	static NoteEnd  note_end;
+
+	switch(ev->type) {
+	case GDK_BUTTON_PRESS:
+		if (ev->button.button == 2) {
+			event_x = ev->button.x;
+			middle_point = x1() + (x2() - x1()) / 2.0L;
+
+			if(event_x <= middle_point) {
+				cursor = Gdk::Cursor(Gdk::LEFT_SIDE);
+				last_x = x1();
+				note_end = NOTE_ON;
+			} else {
+				cursor = Gdk::Cursor(Gdk::RIGHT_SIDE);
+				last_x = x2();
+				note_end = NOTE_OFF;
+			}
+
+			_item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, cursor, ev->motion.time);
+
+			if (_region.mouse_state() == MidiRegionView::SelectTouchDragging) {
+				_mouse2_state = AbsoluteResize;
+			} else {
+				_mouse2_state = RelativeResize;
+			}
+
+			pressed_x = event_x;
+
+			_region.note_selected(this, true);
+			_region.begin_resizing(note_end);
+
+			return true;
+		}
+
+	case GDK_MOTION_NOTIFY:
+		event_x = ev->motion.x;
+
+		if (_mouse2_state == RelativeResize) {
+			_region.update_resizing(note_end, event_x - last_x, true);
+			last_x = event_x;
+			return true;
+		}
+
+		if (_mouse2_state == AbsoluteResize) {
+			_region.update_resizing(note_end, event_x, false);
+			return true;
+		}
+
+	case GDK_BUTTON_RELEASE:
+		event_x = ev->button.x;
+
+		switch (_mouse2_state) {
+		case RelativeResize: // Clicked
+			_item->ungrab(ev->button.time);
+			_region.commit_resizing(note_end, event_x, true);
+			_mouse2_state = None;
+			return true;
+
+		case AbsoluteResize: // Clicked
+			_item->ungrab(ev->button.time);
+			_region.commit_resizing(note_end, event_x, false);
+			_mouse2_state = None;
+			return true;
+
+		default:
+			return CanvasMidiEvent::on_event(ev);
+		}
+
+	default:
+		return CanvasMidiEvent::on_event(ev);
+	}
+}
+
+} // namespace Gnome
+} // namespace Canvas
Index: gtk2_ardour/midi_region_view.cc
===================================================================
--- gtk2_ardour/midi_region_view.cc	(Revision 3144)
+++ gtk2_ardour/midi_region_view.cc	(Arbeitskopie)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2001-2007 Paul Davis 
+    Copyright (C) 2001-2007 Paul Davis
     Author: Dave Robillard
 
     This program is free software; you can redistribute it and/or modify
@@ -39,7 +39,6 @@
 #include "midi_region_view.h"
 #include "midi_streamview.h"
 #include "midi_time_axis.h"
-#include "simplerect.h"
 #include "simpleline.h"
 #include "canvas-hit.h"
 #include "public_editor.h"
@@ -92,7 +91,7 @@
 {
 	if (wfd)
 		midi_region()->midi_source(0)->load_model();
-	
+
 	const Meter& m = trackview.session().tempo_map().meter_at(_region->position());
 	const Tempo& t = trackview.session().tempo_map().tempo_at(_region->position());
 	_default_note_length = m.frames_per_bar(t, trackview.session().frame_rate())
@@ -100,7 +99,7 @@
 
 	_model = midi_region()->midi_source(0)->model();
 	_enable_display = false;
-	
+
 	RegionView::init(basic_color, false);
 
 	compute_colors (basic_color);
@@ -127,7 +126,7 @@
 	}
 
 	midi_region()->midi_source(0)->Switched.connect(sigc::mem_fun(this, &MidiRegionView::switch_source));
-	
+
 	group->signal_event().connect (mem_fun (this, &MidiRegionView::canvas_event), false);
 
 }
@@ -144,12 +143,12 @@
 	nframes_t event_frame = 0;
 
 	static ArdourCanvas::SimpleRect* drag_rect = NULL;
-	
+
 	if (trackview.editor.current_mouse_mode() != MouseNote)
 		return false;
 
 	// Mmmm, spaghetti
-	
+
 	switch (ev->type) {
 	case GDK_KEY_PRESS:
 		if (ev->key.keyval == GDK_Delete && !delete_mod) {
@@ -164,7 +163,7 @@
 			return true;
 		}
 		return false;
-	
+
 	case GDK_KEY_RELEASE:
 		if (ev->key.keyval == GDK_Delete) {
 			if (_mouse_state == EraseTouchDragging) {
@@ -187,18 +186,18 @@
 			_mouse_state = Pressed;
 		_pressed_button = ev->button.button;
 		return true;
-	
+
 	case GDK_ENTER_NOTIFY:
 		/* FIXME: do this on switch to note tool, too, if the pointer is already in */
 		Keyboard::magic_widget_grab_focus();
 		group->grab_focus();
 		break;
-	
+
 	case GDK_MOTION_NOTIFY:
 		event_x = ev->motion.x;
 		event_y = ev->motion.y;
 		group->w2i(event_x, event_y);
-				
+
 		event_frame = trackview.editor.pixel_to_frame(event_x);
 		trackview.editor.snap_to(event_frame);
 
@@ -239,7 +238,7 @@
 
 				drag_rect = new ArdourCanvas::SimpleRect(*group);
 				drag_rect->property_x1() = trackview.editor.frame_to_pixel(event_frame);
-				
+
 				drag_rect->property_y1() = midi_stream_view()->note_to_y(midi_stream_view()->y_to_note(event_y));
 				drag_rect->property_x2() = event_x;
 				drag_rect->property_y2() = drag_rect->property_y1() + floor(midi_stream_view()->note_height());
@@ -279,7 +278,7 @@
 					drag_rect->property_y2() = event_y;
 				else
 					drag_rect->property_y1() = event_y;
-				
+
 				update_drag_selection(drag_start_x, event_x, drag_start_y, event_y);
 			}
 
@@ -294,7 +293,7 @@
 			break;
 		}
 		break;
-	
+
 	case GDK_BUTTON_RELEASE:
 		event_x = ev->motion.x;
 		event_y = ev->motion.y;
@@ -336,7 +335,7 @@
 		default:
 			break;
 		}
-	
+
 	default:
 		break;
 	}
@@ -367,13 +366,13 @@
 
 	// Add a 1 beat long note (for now)
 	const boost::shared_ptr<Note> new_note(new Note(0, stamp, dur, (uint8_t)note, 0x40));
-	
+
 	view->update_bounds(new_note->note());
 
 	MidiModel::DeltaCommand* cmd = _model->new_delta_command("add note");
 	cmd->add(new_note);
 	_model->apply_command(cmd);
-	
+
 	//add_note(new_note);
 }
 
@@ -413,12 +412,12 @@
 	// Don't redisplay the model if we're currently recording and displaying that
 	if (_active_notes)
 		return;
-	
+
 	if (_model) {
 
 		clear_events();
 		begin_write();
-		
+
 		_model->read_lock();
 
 		for (size_t i=0; i < _model->n_notes(); ++i)
@@ -437,7 +436,7 @@
 				continue;
 
 			Gdk::Color col = midi_stream_view()->get_region_color();
-				
+
 			boost::shared_ptr<AutomationRegionView> arv;
 
 			{
@@ -454,7 +453,7 @@
 
 			_automation_children.insert(std::make_pair(i->second->parameter(), arv));
 		}*/
-		
+
 		_model->read_unlock();
 
 	} else {
@@ -466,9 +465,9 @@
 MidiRegionView::~MidiRegionView ()
 {
 	in_destructor = true;
-	
+
 	RegionViewGoingAway (this); /* EMIT_SIGNAL */
-	
+
 	if (_active_notes)
 		end_write();
 
@@ -485,18 +484,18 @@
 	RegionView::region_resized(what_changed);
 
 	if (what_changed & ARDOUR::PositionChanged) {
-	
+
 		if (_enable_display)
 			redisplay_model();
-	
+
 	} else if (what_changed & Change (StartChanged)) {
 
 		//cerr << "MIDI RV START CHANGED" << endl;
 
 	} else if (what_changed & Change (LengthChanged)) {
-		
+
 		//cerr << "MIDI RV LENGTH CHANGED" << endl;
-	
+
 	}
 }
 
@@ -505,7 +504,7 @@
 {
 	RegionView::reset_width_dependent_items(pixel_width);
 	assert(_pixel_width == pixel_width);
-		
+
 	if (_enable_display)
 		redisplay_model();
 }
@@ -516,7 +515,7 @@
 	RegionView::set_y_position_and_height(y, h - 1);
 
 	if (_enable_display) {
-		
+
 		_model->read_lock();
 
 		for (std::vector<CanvasMidiEvent*>::const_iterator i = _events.begin(); i != _events.end(); ++i) {
@@ -531,7 +530,7 @@
 				else {
 					const double y1 = midi_stream_view()->note_to_y(note->note()->note());
 					const double y2 = y1 + floor(midi_stream_view()->note_height());
-					
+
 					if (!canvas_item_visible(note)) {
 						note->show();
 					}
@@ -541,7 +540,7 @@
 				}
 			}
 		}
-		
+
 		_model->read_unlock();
 	}
 
@@ -654,9 +653,9 @@
 	assert(midi_view()->note_mode() == Sustained || midi_view()->note_mode() == Percussive);
 
 	ArdourCanvas::Group* const group = (ArdourCanvas::Group*)get_canvas_group();
-	
+
 	if (midi_view()->note_mode() == Sustained) {
-	
+
 		//cerr << "MRV::add_note sustained " << note->note() << " @ " << note->time()
 		//	<< " .. " << note->end_time() << endl;
 
@@ -682,12 +681,12 @@
 			/* outline all edges */
 			ev_rect->property_outline_what() = (guint32) 0xF;
 		}
-		
+
 		ev_rect->show();
 		_events.push_back(ev_rect);
 
 		MidiGhostRegion* gr;
-		
+
 		for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
 			if ((gr = dynamic_cast<MidiGhostRegion*>(*g)) != 0) {
 				gr->add_note(ev_rect);
@@ -695,10 +694,10 @@
 		}
 
 	} else if (midi_view()->note_mode() == Percussive) {
-		
+
 		//cerr << "MRV::add_note percussive " << note->note() << " @ " << note->time()
 		//	<< " .. " << note->end_time() << endl;
-		
+
 		const double diamond_size = midi_stream_view()->note_height() / 2.0;
 		const double x = trackview.editor.frame_to_pixel((nframes_t)note->time());
 		const double y = midi_stream_view()->note_to_y(note->note()) + ((diamond_size-2) / 4.0);
@@ -709,7 +708,7 @@
 		ev_diamond->property_fill_color_rgba() = note_fill_color(note->velocity());
 		ev_diamond->property_outline_color_rgba() = note_outline_color(note->velocity());
 		_events.push_back(ev_diamond);
-	
+
 	}
 }
 
@@ -744,19 +743,19 @@
 
 	_selection.clear();
 	_selection.insert(ev);
-	
+
 	if ( ! ev->selected())
 		ev->selected(true);
 }
-	
+
 void
 MidiRegionView::note_selected(ArdourCanvas::CanvasMidiEvent* ev, bool add)
 {
 	if ( ! add)
 		clear_selection_except(ev);
-	
+
 	_selection.insert(ev);
-	
+
 	if ( ! ev->selected())
 		ev->selected(true);
 }
@@ -767,9 +766,9 @@
 {
 	if ( ! add)
 		clear_selection_except(ev);
-	
+
 	_selection.erase(ev);
-	
+
 	if (ev->selected())
 		ev->selected(false);
 }
@@ -780,7 +779,7 @@
 {
 	const double last_y = std::min(y1, y2);
 	const double y      = std::max(y1, y2);
-	
+
 	// FIXME: so, so, so much slower than this should be
 
 	if (x1 < x2) {
@@ -806,7 +805,7 @@
 	}
 }
 
-	
+
 void
 MidiRegionView::move_selection(double dx, double dy)
 {
@@ -827,7 +826,7 @@
 			++next;
 
 			command_remove_note(*i);
-			const boost::shared_ptr<Note> copy(new Note(*(*i)->note().get())); 
+			const boost::shared_ptr<Note> copy(new Note(*(*i)->note().get()));
 
 			copy->set_time((*i)->note()->time() + dt);
 			copy->set_note((*i)->note()->note() + dnote);
@@ -840,9 +839,125 @@
 		apply_command();
 	}
 }
-	
 
 void
+MidiRegionView::begin_resizing(CanvasNote::NoteEnd note_end)
+{
+	_resize_data.clear();
+
+	for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
+		CanvasNote *note = dynamic_cast<CanvasNote *> (*i);
+
+		// only insert CanvasNotes into the map
+		if(note) {
+			NoteResizeData *resize_data = new NoteResizeData();
+			resize_data->canvas_note = note;
+
+			SimpleRect *resize_rect = new SimpleRect(*group, note->x1(), note->y1(), note->x2(), note->y2());
+
+			uint fill_color = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->canvasvar_MidiNoteSelectedOutline.get(), 128);
+			fill_color = UINT_INTERPOLATE(fill_color, 0xFFFFFF40, 0.5);
+
+			resize_rect->property_fill_color_rgba() =
+				UINT_INTERPOLATE(
+					note_fill_color(note->note()->velocity()),
+					fill_color,
+					0.85);
+
+			resize_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiNoteSelectedOutline.get();
+			resize_data->resize_rect = resize_rect;
+
+			if(note_end == CanvasNote::NOTE_ON) {
+				resize_data->current_x = note->x1();
+			} else { // NOTE_OFF
+				resize_data->current_x = note->x2();
+			}
+
+			_resize_data.push_back(resize_data);
+		}
+	}
+}
+
+double
+MidiRegionView::snap_to(double x)
+{
+	PublicEditor &editor = trackview.editor;
+
+	nframes_t frame = editor.pixel_to_frame(x);
+	editor.snap_to(frame);
+	return (double) editor.frame_to_pixel(frame);
+}
+
+void
+MidiRegionView::update_resizing(CanvasNote::NoteEnd note_end, double dx, bool relative)
+{
+
+
+	for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
+		SimpleRect     *resize_rect = (*i)->resize_rect;
+		CanvasNote     *canvas_note = (*i)->canvas_note;
+
+		if(relative) {
+			(*i)->current_x = (*i)->current_x + dx;
+		} else {
+			(*i)->current_x = dx;
+		}
+
+		double current_x = (*i)->current_x;
+
+		if(note_end == CanvasNote::NOTE_ON) {
+			resize_rect->property_x1() = snap_to(current_x);
+			resize_rect->property_x2() = canvas_note->x2();
+		} else {
+			resize_rect->property_x2() = snap_to(current_x);
+			resize_rect->property_x1() = canvas_note->x1();
+		}
+	}
+}
+
+void
+MidiRegionView::commit_resizing(CanvasNote::NoteEnd note_end, double event_x, bool relative)
+{
+	start_delta_command();
+
+	for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
+		CanvasNote *canvas_note = (*i)->canvas_note;
+		SimpleRect *resize_rect = (*i)->resize_rect;
+		double      current_x   = (*i)->current_x;
+
+
+		if(!relative) {
+			current_x = event_x;
+		}
+
+		nframes_t current_frame = trackview.editor.pixel_to_frame(current_x);
+		trackview.editor.snap_to(current_frame);
+
+		const boost::shared_ptr<Note> copy(new Note(*(canvas_note->note().get())));
+
+		// resize beginning of note
+		if (note_end == CanvasNote::NOTE_ON && current_frame < copy->end_time()) {
+			command_remove_note(canvas_note);
+			copy->on_event().time() = current_frame;
+			command_add_note(copy);
+		}
+		// resize end of note
+		if (note_end == CanvasNote::NOTE_OFF && current_frame > copy->time()) {
+			command_remove_note(canvas_note);
+			copy->off_event().time() = current_frame;
+			command_add_note(copy);
+		}
+
+		delete resize_rect;
+		delete (*i);
+	}
+
+	_resize_data.clear();
+	apply_command();
+	clear_selection();
+}
+
+void
 MidiRegionView::note_entered(ArdourCanvas::CanvasMidiEvent* ev)
 {
 	if (ev->note() && _mouse_state == EraseTouchDragging) {
@@ -853,8 +968,8 @@
 		note_selected(ev, true);
 	}
 }
-	
 
+
 void
 MidiRegionView::switch_source(boost::shared_ptr<Source> src)
 {
resizing_midi_notes.diff (21,499 bytes)   

drobilla

2008-03-15 00:38

developer   ~0004777

Applied to SVN, but there is a problem: initially dragging on a note to resize it immediately expands the note to a much larger size (looks like double the length) rather than following the drag.

hansfbaier

2008-03-15 10:58

reporter   ~0004778

drobilla: Bug fixed, see new attachments.
Added some doxygen comments in header file as well.

2008-03-15 10:59

 

bugfix_resizing_midi_notes.diff (6,598 bytes)   
Index: gtk2_ardour/midi_region_view.h
===================================================================
--- gtk2_ardour/midi_region_view.h	(Revision 3146)
+++ gtk2_ardour/midi_region_view.h	(Arbeitskopie)
@@ -132,8 +132,34 @@
 	void move_selection(double dx, double dy);
 	void note_dropped(ArdourCanvas::CanvasMidiEvent* ev, double dt, uint8_t dnote);
 
+	/**
+	 * This function is needed to subtract the region start in pixels
+	 * from world coordinates submitted by the mouse
+	 */
+	double get_position_pixels(void);
+
+	/**
+	 * This function is called by CanvasMidiNote when resizing starts,
+	 * i.e. when the user presses mouse-2 on the note
+	 * @param note_end which end of the note, NOTE_ON or NOTE_OFF
+	 */
 	void  begin_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end);
-	void update_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end, double dx, bool relative);
+
+	/**
+	 * This function is called while the user moves the mouse when resizing notes
+	 * @param note_end which end of the note, NOTE_ON or NOTE_OFF
+	 * @param x the difference in mouse motion, ie the motion difference if relative=true
+	 *           or the absolute mouse position (track-relative) if relative is false
+	 * @param relative true if relative resizing is taking place, false if absolute resizing
+	 */
+	void update_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end, double x, bool relative);
+
+	/**
+	 * This function is called while the user releases the mouse button when resizing notes
+	 * @param note_end which end of the note, NOTE_ON or NOTE_OFF
+	 * @param event_x the absolute mouse position (track-relative)
+	 * @param relative true if relative resizing is taking place, false if absolute resizing
+	 */
 	void commit_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end, double event_x, bool relative);
 
 	enum MouseState { None, Pressed, SelectTouchDragging, SelectRectDragging, AddDragging, EraseTouchDragging };
@@ -147,11 +173,11 @@
 
   protected:
 
-    /* this constructor allows derived types
-       to specify their visibility requirements
-       to the TimeAxisViewItem parent class
-    */
-
+    /**
+     * this constructor allows derived types
+     * to specify their visibility requirements
+     * to the TimeAxisViewItem parent class
+     */
     MidiRegionView (ArdourCanvas::Group *,
 	                RouteTimeAxisView&,
 	                boost::shared_ptr<ARDOUR::MidiRegion>,
@@ -177,6 +203,11 @@
 	void clear_selection_except(ArdourCanvas::CanvasMidiEvent* ev);
 	void clear_selection() { clear_selection_except(NULL); }
 	void update_drag_selection(double last_x, double x, double last_y, double y);
+
+	/**
+	 * This function provides the snap function for pixel units (double)
+	 * instead of nframes_t
+	 */
 	double snap_to(double x);
 
 	double _default_note_length;
Index: gtk2_ardour/canvas-note.cc
===================================================================
--- gtk2_ardour/canvas-note.cc	(Revision 3146)
+++ gtk2_ardour/canvas-note.cc	(Arbeitskopie)
@@ -12,23 +12,22 @@
 CanvasNote::on_event(GdkEvent* ev)
 {
 	double          event_x;
-	static double   middle_point, pressed_x, last_x;
+	static double   middle_point, last_x;
 	Gdk::Cursor     cursor;
 	static NoteEnd  note_end;
 
 	switch(ev->type) {
 	case GDK_BUTTON_PRESS:
 		if (ev->button.button == 2) {
+			double region_start = _region.get_position_pixels();
 			event_x = ev->button.x;
-			middle_point = x1() + (x2() - x1()) / 2.0L;
+			middle_point = region_start + x1() + (x2() - x1()) / 2.0L;
 
 			if(event_x <= middle_point) {
 				cursor = Gdk::Cursor(Gdk::LEFT_SIDE);
-				last_x = x1();
 				note_end = NOTE_ON;
 			} else {
 				cursor = Gdk::Cursor(Gdk::RIGHT_SIDE);
-				last_x = x2();
 				note_end = NOTE_OFF;
 			}
 
@@ -40,10 +39,9 @@
 				_mouse2_state = RelativeResize;
 			}
 
-			pressed_x = event_x;
-
 			_region.note_selected(this, true);
 			_region.begin_resizing(note_end);
+			last_x = event_x;
 
 			return true;
 		}
Index: gtk2_ardour/midi_region_view.cc
===================================================================
--- gtk2_ardour/midi_region_view.cc	(Revision 3146)
+++ gtk2_ardour/midi_region_view.cc	(Arbeitskopie)
@@ -840,6 +840,26 @@
 	}
 }
 
+
+double
+MidiRegionView::snap_to(double x)
+{
+	PublicEditor &editor = trackview.editor;
+
+	nframes_t frame = editor.pixel_to_frame(x);
+	editor.snap_to(frame);
+	return (double) editor.frame_to_pixel(frame);
+}
+
+double
+MidiRegionView::get_position_pixels(void)
+{
+	PublicEditor &editor = trackview.editor;
+
+	nframes_t  region_frame  = get_position();
+	return editor.frame_to_pixel(region_frame);
+}
+
 void
 MidiRegionView::begin_resizing(CanvasNote::NoteEnd note_end)
 {
@@ -853,7 +873,13 @@
 			NoteResizeData *resize_data = new NoteResizeData();
 			resize_data->canvas_note = note;
 
-			SimpleRect *resize_rect = new SimpleRect(*group, note->x1(), note->y1(), note->x2(), note->y2());
+			SimpleRect *resize_rect =
+				new SimpleRect(
+						*group,
+						note->x1(),
+						note->y1(),
+						note->x2(),
+						note->y2());
 
 			uint fill_color = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->canvasvar_MidiNoteSelectedOutline.get(), 128);
 			fill_color = UINT_INTERPOLATE(fill_color, 0xFFFFFF40, 0.5);
@@ -878,29 +904,19 @@
 	}
 }
 
-double
-MidiRegionView::snap_to(double x)
-{
-	PublicEditor &editor = trackview.editor;
-
-	nframes_t frame = editor.pixel_to_frame(x);
-	editor.snap_to(frame);
-	return (double) editor.frame_to_pixel(frame);
-}
-
 void
-MidiRegionView::update_resizing(CanvasNote::NoteEnd note_end, double dx, bool relative)
+MidiRegionView::update_resizing(CanvasNote::NoteEnd note_end, double x, bool relative)
 {
-
-
 	for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
 		SimpleRect     *resize_rect = (*i)->resize_rect;
 		CanvasNote     *canvas_note = (*i)->canvas_note;
 
 		if(relative) {
-			(*i)->current_x = (*i)->current_x + dx;
+			cerr << "update: relative\n";
+			(*i)->current_x = (*i)->current_x + x;
 		} else {
-			(*i)->current_x = dx;
+			// x is in track relative, transform it to region relative
+			(*i)->current_x = x - get_position_pixels();
 		}
 
 		double current_x = (*i)->current_x;
@@ -927,8 +943,10 @@
 
 
 		if(!relative) {
-			current_x = event_x;
-		}
+			// event_x is in track relative, transform it to region relative
+			current_x = event_x - get_position_pixels();
+			cerr << "commit: absolute\n";
+		} else cerr << "commit: relative\n";
 
 		nframes_t current_frame = trackview.editor.pixel_to_frame(current_x);
 		trackview.editor.snap_to(current_frame);

2008-03-16 23:21

 

resizing_midi_notes_added_tool_and_fixed_snapto_bugs.diff (161,173 bytes)   
Index: gtk2_ardour/editing_syms.h
===================================================================
--- gtk2_ardour/editing_syms.h	(Revision 3147)
+++ gtk2_ardour/editing_syms.h	(Arbeitskopie)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000-2007 Paul Davis 
+    Copyright (C) 2000-2007 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -63,6 +63,7 @@
 
 MIDIEDITMODE(MidiEditPencil)
 MIDIEDITMODE(MidiEditSelect)
+MIDIEDITMODE(MidiEditResize)
 MIDIEDITMODE(MidiEditErase)
 
 /* Changing this order will break the menu */
Index: gtk2_ardour/canvas-note.h
===================================================================
--- gtk2_ardour/canvas-note.h	(Revision 3147)
+++ gtk2_ardour/canvas-note.h	(Arbeitskopie)
@@ -55,14 +55,14 @@
 		NOTE_OFF
 	};
 
-	enum Mouse2State {
+	enum NoteState {
 		None,
 		RelativeResize,
 		AbsoluteResize
 	};
 
 protected:
-	Mouse2State _mouse2_state;
+	NoteState _note_state;
 
 private:
 	// single click resizing with mouse-2
Index: gtk2_ardour/editor_mouse.cc
===================================================================
--- gtk2_ardour/editor_mouse.cc	(Revision 3147)
+++ gtk2_ardour/editor_mouse.cc	(Arbeitskopie)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000-2001 Paul Davis 
+    Copyright (C) 2000-2001 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -84,7 +84,7 @@
 	Gdk::ModifierType mask;
 	Glib::RefPtr<Gdk::Window> canvas_window = const_cast<Editor*>(this)->track_canvas.get_window();
 	Glib::RefPtr<const Gdk::Window> pointer_window;
-	
+
 	pointer_window = canvas_window->get_pointer (x, y, mask);
 
 	if (pointer_window == track_canvas.get_bin_window()) {
@@ -109,7 +109,7 @@
 	event.type = GDK_BUTTON_RELEASE;
 	event.button.x = wx;
 	event.button.y = wy;
-	
+
 	where = event_frame (&event, 0, 0);
 	return true;
 }
@@ -156,7 +156,7 @@
 	   position is negative (as can be the case with motion events in particular),
 	   the frame location is always positive.
 	*/
-	
+
 	return pixel_to_frame (*pcx);
 }
 
@@ -203,7 +203,7 @@
 			set_mouse_mode (m);
 		}
 		break;
-	
+
 	case MouseNote:
 		if (mouse_note_button.get_active()) {
 			set_mouse_mode (m);
@@ -213,7 +213,7 @@
 	default:
 		break;
 	}
-}	
+}
 
 Gdk::Cursor*
 Editor::which_grabber_cursor ()
@@ -255,7 +255,7 @@
 	case MouseAudition:
 		current_canvas_cursor = speaker_cursor;
 		break;
-	
+
 	case MouseNote:
 		set_midi_edit_cursor (current_midi_edit_mode());
 		break;
@@ -276,7 +276,7 @@
 	if (!force && m == mouse_mode) {
 		return;
 	}
-	
+
 	mouse_mode = m;
 
 	instant_save ();
@@ -296,7 +296,7 @@
 
 	} else {
 
-		/* 
+		/*
 		   in range mode,show the range selection.
 		*/
 
@@ -307,11 +307,11 @@
 		}
 	}
 
-	/* XXX the hack of unsetting all other buttons should go 
+	/* XXX the hack of unsetting all other buttons should go
 	   away once GTK2 allows us to use regular radio buttons drawn like
 	   normal buttons, rather than my silly GroupedButton hack.
 	*/
-	
+
 	ignore_mouse_mode_toggle = true;
 
 	switch (mouse_mode) {
@@ -338,7 +338,7 @@
 	case MouseAudition:
 		mouse_audition_button.set_active (true);
 		break;
-	
+
 	case MouseNote:
 		mouse_note_button.set_active (true);
 		set_midi_edit_cursor (current_midi_edit_mode());
@@ -351,7 +351,7 @@
 		midi_toolbar_frame.hide();
 
 	ignore_mouse_mode_toggle = false;
-	
+
 	set_canvas_cursor ();
 }
 
@@ -373,12 +373,12 @@
 		if (next) set_mouse_mode (MouseGain);
 		else set_mouse_mode (MouseRange);
 		break;
-	
+
 	case MouseGain:
 		if (next) set_mouse_mode (MouseTimeFX);
 		else set_mouse_mode (MouseZoom);
 		break;
-	
+
 	case MouseTimeFX:
 		if (next) set_mouse_mode (MouseAudition);
 		else set_mouse_mode (MouseGain);
@@ -388,7 +388,7 @@
 		if (next) set_mouse_mode (MouseObject);
 		else set_mouse_mode (MouseTimeFX);
 		break;
-	
+
 	case MouseNote:
 		if (next) set_mouse_mode (MouseObject);
 		else set_mouse_mode (MouseAudition);
@@ -414,6 +414,11 @@
 			set_midi_edit_mode (m);
 		break;
 
+	case MidiEditResize:
+		if (midi_tool_resize_button.get_active())
+			set_midi_edit_mode (m);
+		break;
+
 	case MidiEditErase:
 		if (midi_tool_erase_button.get_active())
 			set_midi_edit_mode (m);
@@ -424,7 +429,7 @@
 	}
 
 	set_midi_edit_cursor(m);
-}	
+}
 
 
 void
@@ -437,11 +442,11 @@
 	if (!force && m == midi_edit_mode) {
 		return;
 	}
-	
+
 	midi_edit_mode = m;
 
 	instant_save ();
-	
+
 	ignore_midi_edit_mode_toggle = true;
 
 	switch (midi_edit_mode) {
@@ -453,6 +458,10 @@
 		midi_tool_select_button.set_active (true);
 		break;
 
+	case MidiEditResize:
+		midi_tool_resize_button.set_active (true);
+		break;
+
 	case MidiEditErase:
 		midi_tool_erase_button.set_active (true);
 		break;
@@ -479,6 +488,10 @@
 		current_canvas_cursor = midi_select_cursor;
 		break;
 
+	case MidiEditResize:
+		current_canvas_cursor = midi_resize_cursor;
+		break;
+
 	case MidiEditErase:
 		current_canvas_cursor = midi_erase_cursor;
 		break;
@@ -502,27 +515,27 @@
 	     (mouse_mode != MouseRange)) ||
 
 	    (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE || event->button.button > 3)) {
-		
+
 		return;
 	}
 
 	if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) {
 
 		if ((event->button.state & Keyboard::RelevantModifierKeyMask) && event->button.button != 1) {
-			
+
 			/* almost no selection action on modified button-2 or button-3 events */
-		
+
 			if (item_type != RegionItem && event->button.button != 2) {
 				return;
 			}
 		}
 	}
-	    
+
 	Selection::Operation op = Keyboard::selection_type (event->button.state);
 	bool press = (event->type == GDK_BUTTON_PRESS);
 
 	// begin_reversible_command (_("select on click"));
-	
+
 	switch (item_type) {
 	case RegionItem:
 		if (mouse_mode != MouseRange) {
@@ -531,7 +544,7 @@
 			set_selected_track_as_side_effect ();
 		}
 		break;
-		
+
  	case RegionViewNameHighlight:
  	case RegionViewName:
 		if (mouse_mode != MouseRange) {
@@ -559,7 +572,7 @@
 			set_selected_control_point_from_click (op, false);
 		}
 		break;
-		
+
 	case StreamItem:
 		/* for context click or range selection, select track */
 		if (event->button.button == 3) {
@@ -568,11 +581,11 @@
 			set_selected_track_as_side_effect ();
 		}
 		break;
-		    
+
 	case AutomationTrackItem:
 		set_selected_track_as_side_effect (true);
 		break;
-		
+
 	default:
 		break;
 	}
@@ -588,12 +601,12 @@
 	}
 
 	button_selection (item, event, item_type);
-	
+
 	if (drag_info.item == 0 &&
 	    (Keyboard::is_delete_event (&event->button) ||
 	     Keyboard::is_context_menu_event (&event->button) ||
 	     Keyboard::is_edit_event (&event->button))) {
-		
+
 		/* handled by button release */
 		return true;
 	}
@@ -612,7 +625,7 @@
 			   not on the main track canvas or because we want
 			   them to be modeless.
 			*/
-			
+
 			switch (item_type) {
 			case PlayheadCursorItem:
 				start_cursor_grab (item, event);
@@ -647,19 +660,19 @@
 
 			case MeterBarItem:
 				return true;
-				
+
 			case RangeMarkerBarItem:
-				start_range_markerbar_op (item, event, CreateRangeMarker); 
+				start_range_markerbar_op (item, event, CreateRangeMarker);
 				return true;
 				break;
 
 			case CdMarkerBarItem:
-				start_range_markerbar_op (item, event, CreateCDMarker); 
+				start_range_markerbar_op (item, event, CreateCDMarker);
 				return true;
 				break;
 
 			case TransportMarkerBarItem:
-				start_range_markerbar_op (item, event, CreateTransportMarker); 
+				start_range_markerbar_op (item, event, CreateTransportMarker);
 				return true;
 				break;
 
@@ -674,13 +687,13 @@
 			case StartSelectionTrimItem:
 				start_selection_op (item, event, SelectionStartTrim);
 				break;
-				
+
 			case EndSelectionTrimItem:
 				start_selection_op (item, event, SelectionEndTrim);
 				break;
 
 			case SelectionItem:
-				if (Keyboard::modifier_state_contains 
+				if (Keyboard::modifier_state_contains
 				    (event->button.state, Keyboard::ModifierMask(Keyboard::SecondaryModifier))) {
 					// contains and not equals because I can't use alt as a modifier alone.
 					start_selection_grab (item, event);
@@ -699,11 +712,11 @@
 			}
 			return true;
 			break;
-			
+
 		case MouseObject:
 			if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) &&
 			    event->type == GDK_BUTTON_PRESS) {
-				
+
 				start_rubberband_select (item, event);
 
 			} else if (event->type == GDK_BUTTON_PRESS) {
@@ -712,7 +725,7 @@
 				case FadeInHandleItem:
 					start_fade_in_grab (item, event);
 					return true;
-					
+
 				case FadeOutHandleItem:
 					start_fade_out_grab (item, event);
 					return true;
@@ -726,12 +739,12 @@
 						start_region_grab (item, event);
 					}
 					break;
-					
+
 				case RegionViewNameHighlight:
 					start_trim (item, event);
 					return true;
 					break;
-					
+
 				case RegionViewName:
 					/* rename happens on edit clicks */
 						start_trim (clicked_regionview->get_name_highlight(), event);
@@ -742,7 +755,7 @@
 					start_control_point_grab (item, event);
 					return true;
 					break;
-					
+
 				case AutomationLineItem:
 					start_line_grab_from_line (item, event);
 					return true;
@@ -752,7 +765,7 @@
 				case AutomationTrackItem:
 					start_rubberband_select (item, event);
 					break;
-					
+
 #ifdef WITH_CMT
 				case ImageFrameHandleStartItem:
 					imageframe_start_handle_op(item, event) ;
@@ -779,7 +792,7 @@
 #endif
 
 				case MarkerBarItem:
-					
+
 					break;
 
 				default:
@@ -788,7 +801,7 @@
 			}
 			return true;
 			break;
-			
+
 		case MouseGain:
 			switch (item_type) {
 			case RegionItem:
@@ -858,7 +871,7 @@
 		case MouseNote:
 			start_create_region_grab (item, event);
 			break;
-		
+
 		default:
 			break;
 		}
@@ -881,28 +894,28 @@
 					start_control_point_grab (item, event);
 					return true;
 					break;
-					
+
 				default:
 					break;
 				}
 			}
-			
-			
+
+
 			switch (item_type) {
 			case RegionViewNameHighlight:
 				start_trim (item, event);
 				return true;
 				break;
-				
+
 			case RegionViewName:
 				start_trim (clicked_regionview->get_name_highlight(), event);
 				return true;
 				break;
-				
+
 			default:
 				break;
 			}
-			
+
 			break;
 
 		case MouseRange:
@@ -911,8 +924,8 @@
 			}
 			return true;
 			break;
-					
-				
+
+
 		case MouseZoom:
 			if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
 				temporal_zoom_session();
@@ -946,7 +959,7 @@
 	AutomationTimeAxisView* atv = 0;
 
 	/* no action if we're recording */
-						
+
 	if (session && session->actively_recording()) {
 		return true;
 	}
@@ -959,11 +972,11 @@
 			return true;
 		}
 	}
-	
+
 	button_selection (item, event, item_type);
 
 	/* edit events get handled here */
-	
+
 	if (drag_info.item == 0 && Keyboard::is_edit_event (&event->button)) {
 		switch (item_type) {
 		case RegionItem:
@@ -973,11 +986,11 @@
 		case TempoMarkerItem:
 			edit_tempo_marker (item);
 			break;
-			
+
 		case MeterMarkerItem:
 			edit_meter_marker (item);
 			break;
-			
+
 		case RegionViewName:
 			if (clicked_regionview->name_active()) {
 				return mouse_rename_region (item, event);
@@ -1007,17 +1020,17 @@
 			case FadeOutHandleItem:
 				popup_fade_context_menu (1, event->button.time, item, item_type);
 				break;
-			
+
 			case StreamItem:
 				popup_track_context_menu (1, event->button.time, item_type, false, where);
 				break;
-				
+
 			case RegionItem:
 			case RegionViewNameHighlight:
 			case RegionViewName:
 				popup_track_context_menu (1, event->button.time, item_type, false, where);
 				break;
-				
+
 			case SelectionItem:
 				popup_track_context_menu (1, event->button.time, item_type, true, where);
 				break;
@@ -1026,8 +1039,8 @@
 				popup_track_context_menu (1, event->button.time, item_type, false, where);
 				break;
 
-			case MarkerBarItem: 
-			case RangeMarkerBarItem: 
+			case MarkerBarItem:
+			case RangeMarkerBarItem:
 			case TransportMarkerBarItem:
 			case CdMarkerBarItem:
 			case TempoBarItem:
@@ -1042,11 +1055,11 @@
 			case TempoMarkerItem:
 				tm_marker_context_menu (&event->button, item);
 				break;
-				
+
 			case MeterMarkerItem:
 				tm_marker_context_menu (&event->button, item);
 				break;
-			
+
 			case CrossfadeViewItem:
 				popup_track_context_menu (1, event->button.time, item_type, false, where);
 				break;
@@ -1065,7 +1078,7 @@
 				popup_marker_time_axis_edit_menu(1, event->button.time, item, false) ;
 				break ;
 #endif
-				
+
 			default:
 				break;
 			}
@@ -1082,7 +1095,7 @@
 		case TempoMarkerItem:
 			remove_tempo_marker (item);
 			break;
-			
+
 		case MeterMarkerItem:
 			remove_meter_marker (item);
 			break;
@@ -1096,7 +1109,7 @@
 				remove_clicked_region ();
 			}
 			break;
-			
+
 		case ControlPointItem:
 			if (mouse_mode == MouseGain) {
 				remove_gain_control_point (item, event);
@@ -1145,7 +1158,7 @@
 			}
 			mouse_add_new_tempo_event (where);
 			return true;
-			
+
 		case MeterBarItem:
 			mouse_add_new_meter_event (pixel_to_frame (event->button.x));
 			return true;
@@ -1164,9 +1177,9 @@
 					atv->add_automation_event (item, event, where, event->button.y);
 				}
 				return true;
-				
+
 				break;
-				
+
 			default:
 				break;
 			}
@@ -1184,7 +1197,7 @@
 				dynamic_cast<AudioRegionView*>(clicked_regionview)->add_gain_point_event (item, event);
 				return true;
 				break;
-				
+
 			case AutomationTrackItem:
 				dynamic_cast<AutomationTimeAxisView*>(clicked_axisview)->
 					add_automation_event (item, event, where, event->button.y);
@@ -1194,7 +1207,7 @@
 				break;
 			}
 			break;
-			
+
 		case MouseAudition:
 			_scrubbing = false;
 			track_canvas.get_window()->set_cursor (*current_canvas_cursor);
@@ -1212,7 +1225,7 @@
 				session->request_transport_speed (0.0);
  			}
 			break;
-			
+
 		default:
 			break;
 
@@ -1224,7 +1237,7 @@
 
 	case 2:
 		switch (mouse_mode) {
-			
+
 		case MouseObject:
 			switch (item_type) {
 			case RegionItem:
@@ -1236,29 +1249,29 @@
 					// Button2 click is unused
 				}
 				return true;
-				
+
 				break;
-				
+
 			default:
 				break;
 			}
 			break;
-			
+
 		case MouseRange:
-			
+
 			// x_style_paste (where, 1.0);
 			return true;
 			break;
-			
+
 		default:
 			break;
 		}
 
 		break;
-	
+
 	case 3:
 		break;
-		
+
 	default:
 		break;
 	}
@@ -1271,7 +1284,7 @@
 	ControlPoint* cp;
 	Marker * marker;
 	double fraction;
-	
+
 	if (last_item_entered != item) {
 		last_item_entered = item;
 		last_item_entered_n = 0;
@@ -1314,7 +1327,7 @@
 			}
 		}
 		break;
-			
+
 	case AutomationLineItem:
 		if (mouse_mode == MouseGain || mouse_mode == MouseObject) {
 			{
@@ -1327,7 +1340,7 @@
 			}
 		}
 		break;
-		
+
 	case RegionViewNameHighlight:
 		if (is_drawable() && mouse_mode == MouseObject) {
 			track_canvas.get_window()->set_cursor (*trimmer_cursor);
@@ -1363,14 +1376,14 @@
 		break;
 
 	case RegionViewName:
-		
+
 		/* when the name is not an active item, the entire name highlight is for trimming */
 
 		if (!reinterpret_cast<RegionView *> (item->get_data ("regionview"))->name_active()) {
 			if (mouse_mode == MouseObject && is_drawable()) {
 				track_canvas.get_window()->set_cursor (*trimmer_cursor);
 			}
-		} 
+		}
 		break;
 
 
@@ -1479,14 +1492,14 @@
 				cp->set_visible (false);
 			}
 		}
-		
+
 		if (is_drawable()) {
 			track_canvas.get_window()->set_cursor (*current_canvas_cursor);
 		}
 
 		hide_verbose_canvas_cursor ();
 		break;
-		
+
 	case RegionViewNameHighlight:
 	case StartSelectionTrimItem:
 	case EndSelectionTrimItem:
@@ -1536,7 +1549,7 @@
 			time_canvas.get_window()->set_cursor (*timebar_cursor);
 		}
 		break;
-		
+
 	case MarkerItem:
 		if ((marker = static_cast<Marker *> (item->get_data ("marker"))) == 0) {
 			break;
@@ -1548,7 +1561,7 @@
 		// fall through
 	case MeterMarkerItem:
 	case TempoMarkerItem:
-		
+
 		if (is_drawable()) {
 			time_canvas.get_window()->set_cursor (*timebar_cursor);
 		}
@@ -1574,7 +1587,7 @@
 			Glib::signal_idle().connect (mem_fun(*this, &Editor::left_automation_track));
 		}
 		break;
-		
+
 	default:
 		break;
 	}
@@ -1597,19 +1610,19 @@
 {
 	if (event->motion.is_hint) {
 		gint x, y;
-		
+
 		/* We call this so that MOTION_NOTIFY events continue to be
 		   delivered to the canvas. We need to do this because we set
 		   Gdk::POINTER_MOTION_HINT_MASK on the canvas. This reduces
 		   the density of the events, at the expense of a round-trip
 		   to the server. Given that this will mostly occur on cases
 		   where DISPLAY = :0.0, and given the cost of what the motion
-		   event might do, its a good tradeoff.  
+		   event might do, its a good tradeoff.
 		*/
-		
+
 		track_canvas.get_pointer (x, y);
 	}
-	
+
 	if (current_stepping_trackview) {
 		/* don't keep the persistent stepped trackview if the mouse moves */
 		current_stepping_trackview = 0;
@@ -1640,11 +1653,11 @@
 				scrubbing_direction = 1;
 
 			} else {
-				
+
 				if (last_scrub_x > drag_info.current_pointer_x) {
 
 					/* pointer moved to the left */
-					
+
 					if (scrubbing_direction > 0) {
 
 						/* we reversed direction to go backwards */
@@ -1655,14 +1668,14 @@
 					} else {
 
 						/* still moving to the left (backwards) */
-						
+
 						scrub_reversals = 0;
 						scrub_reverse_distance = 0;
 
 						delta = 0.01 * (last_scrub_x - drag_info.current_pointer_x);
 						session->request_transport_speed (session->transport_speed() - delta);
 					}
-					
+
 				} else {
 					/* pointer moved to the right */
 
@@ -1677,7 +1690,7 @@
 
 						scrub_reversals = 0;
 						scrub_reverse_distance = 0;
-						
+
 						delta = 0.01 * (drag_info.current_pointer_x - last_scrub_x);
 						session->request_transport_speed (session->transport_speed() + delta);
 					}
@@ -1698,7 +1711,7 @@
 						session->request_transport_speed (0.1);
 						scrubbing_direction = 1;
 					}
-					
+
 					scrub_reverse_distance = 0;
 					scrub_reversals = 0;
 				}
@@ -1719,9 +1732,9 @@
 
 			bool x_threshold_passed =  (::llabs ((nframes64_t) (drag_info.current_pointer_x - drag_info.grab_x)) > 4LL);
 			bool y_threshold_passed =  (::llabs ((nframes64_t) (drag_info.current_pointer_y - drag_info.grab_y)) > 4LL);
-			
+
 			drag_info.move_threshold_passed = (x_threshold_passed || y_threshold_passed);
-			
+
 			// and change the initial grab loc/frame if this drag info wants us to
 
 			if (drag_info.want_move_threshold && drag_info.move_threshold_passed) {
@@ -1765,7 +1778,7 @@
 		  goto handled;
 	  }
 	  goto not_handled;
-	  
+
 	default:
 		break;
 	}
@@ -1795,7 +1808,7 @@
 	track_canvas_motion (event);
 	// drag_info.last_pointer_frame = drag_info.current_pointer_frame;
 	return true;
-	
+
   not_handled:
 	return false;
 }
@@ -1889,7 +1902,7 @@
 	if (drag_info.item == 0) {
 		return false;
 	}
-	
+
 	drag_info.item->ungrab (event->button.time);
 
 	if (drag_info.finished_callback) {
@@ -1937,7 +1950,7 @@
 
 	AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
 
-	drag_info.pointer_frame_offset = drag_info.grab_frame - ((nframes_t) arv->audio_region()->fade_in()->back()->when + arv->region()->position());	
+	drag_info.pointer_frame_offset = drag_info.grab_frame - ((nframes_t) arv->audio_region()->fade_in()->back()->when + arv->region()->position());
 }
 
 void
@@ -1964,17 +1977,17 @@
 		fade_length = arv->region()->length();
 	} else {
 		fade_length = pos - arv->region()->position();
-	}		
+	}
 	/* mapover the region selection */
 
 	for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
 
 		AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
-		
+
 		if (!tmp) {
 			continue;
 		}
-	
+
 		tmp->reset_fade_in_shape_width (fade_length);
 	}
 
@@ -2005,23 +2018,23 @@
 	} else {
 		fade_length = pos - arv->region()->position();
 	}
-		
+
 	begin_reversible_command (_("change fade in length"));
 
 	for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
 
 		AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
-		
+
 		if (!tmp) {
 			continue;
 		}
-	
+
 		boost::shared_ptr<AutomationList> alist = tmp->audio_region()->fade_in();
 		XMLNode &before = alist->get_state();
 
 		tmp->audio_region()->set_fade_in_length (fade_length);
 		tmp->audio_region()->set_fade_in_active (true);
-		
+
 		XMLNode &after = alist->get_state();
 		session->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
 	}
@@ -2045,7 +2058,7 @@
 
 	AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
 
-	drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region()->length() - (nframes_t) arv->audio_region()->fade_out()->back()->when + arv->region()->position());	
+	drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region()->length() - (nframes_t) arv->audio_region()->fade_out()->back()->when + arv->region()->position());
 }
 
 void
@@ -2064,7 +2077,7 @@
 	if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
 		snap_to (pos);
 	}
-	
+
 	if (pos > (arv->region()->last_frame() - 64)) {
 		fade_length = 64; // this should really be a minimum fade defined somewhere
 	}
@@ -2074,17 +2087,17 @@
 	else {
 		fade_length = arv->region()->last_frame() - pos;
 	}
-		
+
 	/* mapover the region selection */
 
 	for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
 
 		AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
-		
+
 		if (!tmp) {
 			continue;
 		}
-	
+
 		tmp->reset_fade_out_shape_width (fade_length);
 	}
 
@@ -2128,14 +2141,14 @@
 	for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
 
 		AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
-		
+
 		if (!tmp) {
 			continue;
 		}
-	
+
 		boost::shared_ptr<AutomationList> alist = tmp->audio_region()->fade_out();
 		XMLNode &before = alist->get_state();
-		
+
 		tmp->audio_region()->set_fade_out_length (fade_length);
 		tmp->audio_region()->set_fade_out_active (true);
 
@@ -2164,7 +2177,7 @@
 
 	if (cursor == playhead_cursor) {
 		_dragging_playhead = true;
-		
+
 		if (session && drag_info.was_rolling) {
 			session->request_stop ();
 		}
@@ -2174,8 +2187,8 @@
 		}
 	}
 
-	drag_info.pointer_frame_offset = drag_info.grab_frame - cursor->current_frame;	
-	
+	drag_info.pointer_frame_offset = drag_info.grab_frame - cursor->current_frame;
+
 	show_verbose_time_cursor (cursor->current_frame, 10);
 }
 
@@ -2184,24 +2197,24 @@
 {
 	Cursor* cursor = (Cursor *) drag_info.data;
 	nframes_t adjusted_frame;
-	
+
 	if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
 		adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
 	}
 	else {
 		adjusted_frame = 0;
 	}
-	
+
 	if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
 		if (cursor == playhead_cursor) {
 			snap_to (adjusted_frame);
 		}
 	}
-	
+
 	if (adjusted_frame == drag_info.last_pointer_frame) return;
 
 	cursor->set_position (adjusted_frame);
-	
+
 	UpdateAllTransportClocks (cursor->current_frame);
 
 	show_verbose_time_cursor (cursor->current_frame, 10);
@@ -2214,16 +2227,16 @@
 Editor::cursor_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
 {
 	if (drag_info.first_move) return;
-	
+
 	cursor_drag_motion_callback (item, event);
 
 	_dragging_playhead = false;
-	
+
 	if (item == &playhead_cursor->canvas_item) {
 		if (session) {
 			session->request_locate (playhead_cursor->current_frame, drag_info.was_rolling);
 		}
-	} 
+	}
 }
 
 void
@@ -2267,7 +2280,7 @@
 	_dragging_edit_point = true;
 
 	drag_info.copied_location = new Location (*location);
-	drag_info.pointer_frame_offset = drag_info.grab_frame - (is_start ? location->start() : location->end());	
+	drag_info.pointer_frame_offset = drag_info.grab_frame - (is_start ? location->start() : location->end());
 
 	update_marker_drag_item (location);
 
@@ -2306,7 +2319,7 @@
 void
 Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 {
-	nframes_t f_delta;	
+	nframes_t f_delta;
 	Marker* marker = (Marker *) drag_info.data;
 	Location  *real_location;
 	Location  *copy_location;
@@ -2325,13 +2338,13 @@
 	if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
 		snap_to (newframe, 0, true);
 	}
-	
-	if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) { 
+
+	if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) {
 		return;
 	}
 
 	/* call this to find out if its the start or end */
-	
+
 	if ((real_location = find_location_from_marker (marker, is_start)) == 0) {
 		return;
 	}
@@ -2341,11 +2354,11 @@
 	}
 
 	/* use the copy that we're "dragging" around */
-	
+
 	copy_location = drag_info.copied_location;
 
 	f_delta = copy_location->end() - copy_location->start();
-	
+
 	if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
 		move_both = true;
 	}
@@ -2358,26 +2371,26 @@
 	} else {
 
 		if (is_start) { // start-of-range marker
-			
+
 			if (move_both) {
 				copy_location->set_start (newframe);
 				copy_location->set_end (newframe + f_delta);
 			} else 	if (newframe < copy_location->end()) {
 				copy_location->set_start (newframe);
-			} else { 
+			} else {
 				snap_to (next, 1, true);
 				copy_location->set_end (next);
 				copy_location->set_start (newframe);
 			}
-			
+
 		} else { // end marker
-			
+
 			if (move_both) {
 				copy_location->set_end (newframe);
 				copy_location->set_start (newframe - f_delta);
 			} else if (newframe > copy_location->start()) {
 				copy_location->set_end (newframe);
-				
+
 			} else if (newframe > 0) {
 				snap_to (next, -1, true);
 				copy_location->set_start (next);
@@ -2407,13 +2420,13 @@
 	}
 
 	_dragging_edit_point = false;
-	
+
 	Marker* marker = (Marker *) drag_info.data;
 	bool is_start;
 
 	begin_reversible_command ( _("move marker") );
 	XMLNode &before = session->locations()->get_state();
-	
+
 	Location * location = find_location_from_marker (marker, is_start);
 
 	if (location) {
@@ -2432,7 +2445,7 @@
 	XMLNode &after = session->locations()->get_state();
 	session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
 	commit_reversible_command ();
-	
+
 	marker_drag_line->hide();
 	range_marker_drag_rect->hide();
 }
@@ -2464,7 +2477,7 @@
 
 	start_grab (event);
 
-	drag_info.pointer_frame_offset = drag_info.grab_frame - meter_marker->meter().frame();	
+	drag_info.pointer_frame_offset = drag_info.grab_frame - meter_marker->meter().frame();
 
 	show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
 }
@@ -2481,12 +2494,12 @@
 	}
 
 	meter_marker = dynamic_cast<MeterMarker*> (marker);
-	
+
 	// create a dummy marker for visual representation of moving the copy.
 	// The actual copying is not done before we reach the finish callback.
 	char name[64];
 	snprintf (name, sizeof(name), "%g/%g", meter_marker->meter().beats_per_bar(), meter_marker->meter().note_divisor ());
-	MeterMarker* new_marker = new MeterMarker(*this, *meter_group, ARDOUR_UI::config()->canvasvar_MeterMarker.get(), name, 
+	MeterMarker* new_marker = new MeterMarker(*this, *meter_group, ARDOUR_UI::config()->canvasvar_MeterMarker.get(), name,
 						  *new MeterSection(meter_marker->meter()));
 
 	drag_info.item = &new_marker->the_item();
@@ -2497,7 +2510,7 @@
 
 	start_grab (event);
 
-	drag_info.pointer_frame_offset = drag_info.grab_frame - meter_marker->meter().frame();	
+	drag_info.pointer_frame_offset = drag_info.grab_frame - meter_marker->meter().frame();
 
 	show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
 }
@@ -2514,16 +2527,16 @@
 	else {
 		adjusted_frame = 0;
 	}
-	
+
 	if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
 		snap_to (adjusted_frame);
 	}
-	
+
 	if (adjusted_frame == drag_info.last_pointer_frame) return;
 
 	marker->set_position (adjusted_frame);
-	
-	
+
+
 	drag_info.last_pointer_frame = adjusted_frame;
 	drag_info.first_move = false;
 
@@ -2536,13 +2549,13 @@
 	if (drag_info.first_move) return;
 
 	meter_marker_drag_motion_callback (drag_info.item, event);
-	
+
 	MeterMarker* marker = (MeterMarker *) drag_info.data;
 	BBT_Time when;
-	
+
 	TempoMap& map (session->tempo_map());
 	map.bbt_time (drag_info.last_pointer_frame, when);
-	
+
 	if (drag_info.copy == true) {
 		begin_reversible_command (_("copy meter mark"));
 		XMLNode &before = map.get_state();
@@ -2594,7 +2607,7 @@
 
 	start_grab (event);
 
-	drag_info.pointer_frame_offset = drag_info.grab_frame - tempo_marker->tempo().frame();	
+	drag_info.pointer_frame_offset = drag_info.grab_frame - tempo_marker->tempo().frame();
 	show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
 }
 
@@ -2618,7 +2631,7 @@
 	// The actual copying is not done before we reach the finish callback.
 	char name[64];
 	snprintf (name, sizeof (name), "%.2f", tempo_marker->tempo().beats_per_minute());
-	TempoMarker* new_marker = new TempoMarker(*this, *tempo_group, ARDOUR_UI::config()->canvasvar_TempoMarker.get(), name, 
+	TempoMarker* new_marker = new TempoMarker(*this, *tempo_group, ARDOUR_UI::config()->canvasvar_TempoMarker.get(), name,
 						  *new TempoSection(tempo_marker->tempo()));
 
 	drag_info.item = &new_marker->the_item();
@@ -2639,7 +2652,7 @@
 {
 	TempoMarker* marker = (TempoMarker *) drag_info.data;
 	nframes_t adjusted_frame;
-	
+
 	if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
 		adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
 	}
@@ -2650,13 +2663,13 @@
 	if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
 		snap_to (adjusted_frame);
 	}
-	
+
 	if (adjusted_frame == drag_info.last_pointer_frame) return;
 
 	/* OK, we've moved far enough to make it worth actually move the thing. */
-		
+
 	marker->set_position (adjusted_frame);
-	
+
 	show_verbose_time_cursor (adjusted_frame, 10);
 
 	drag_info.last_pointer_frame = adjusted_frame;
@@ -2667,12 +2680,12 @@
 Editor::tempo_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
 {
 	if (drag_info.first_move) return;
-	
+
 	tempo_marker_drag_motion_callback (drag_info.item, event);
-	
+
 	TempoMarker* marker = (TempoMarker *) drag_info.data;
 	BBT_Time when;
-	
+
 	TempoMap& map (session->tempo_map());
 	map.bbt_time (drag_info.last_pointer_frame, when);
 
@@ -2683,7 +2696,7 @@
 		XMLNode &after = map.get_state();
 		session->add_command (new MementoCommand<TempoMap>(map, &before, &after));
 		commit_reversible_command ();
-		
+
 		// delete the dummy marker we used for visual representation of copying.
 		// a new visual marker will show up automatically.
 		delete marker;
@@ -2709,7 +2722,7 @@
 
 	// We shouldn't remove the first or last gain point
 	if (control_point->line().is_last_point(*control_point) ||
-		control_point->line().is_first_point(*control_point)) {	
+		control_point->line().is_first_point(*control_point)) {
 		return;
 	}
 
@@ -2758,7 +2771,7 @@
 	control_point->line().start_drag (control_point, drag_info.grab_frame, 0);
 
 	double fraction = 1.0 - ((control_point->get_y() - control_point->line().y_position()) / (double)control_point->line().height());
-	set_verbose_canvas_cursor (control_point->line().get_verbose_cursor_string (fraction), 
+	set_verbose_canvas_cursor (control_point->line().get_verbose_cursor_string (fraction),
 				   drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20);
 
 	show_verbose_canvas_cursor ();
@@ -2826,7 +2839,7 @@
 	}
 
 	cp->line().point_drag (*cp, cx_frames , fraction, push);
-	
+
 	set_verbose_canvas_cursor_text (cp->line().get_verbose_cursor_string (fraction));
 
 	drag_info.first_move = false;
@@ -2840,7 +2853,7 @@
 	if (drag_info.first_move) {
 
 		/* just a click */
-		
+
 		if ((event->type == GDK_BUTTON_RELEASE) && (event->button.button == 1) && Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
 			reset_point_selection ();
 		}
@@ -2868,7 +2881,7 @@
 Editor::start_line_grab_from_line (ArdourCanvas::Item* item, GdkEvent* event)
 {
 	AutomationLine* al;
-	
+
 	if ((al = reinterpret_cast<AutomationLine*> (item->get_data ("line"))) == 0) {
 		fatal << _("programming error: line canvas item has no line pointer!") << endmsg;
 		/*NOTREACHED*/
@@ -2893,7 +2906,7 @@
 	line->parent_group().w2i (cx, cy);
 	frame_within_region = (nframes_t) floor (cx * frames_per_unit);
 
-	if (!line->control_points_adjacent (frame_within_region, current_line_drag_info.before, 
+	if (!line->control_points_adjacent (frame_within_region, current_line_drag_info.before,
 					    current_line_drag_info.after)) {
 		/* no adjacent points */
 		return;
@@ -2909,7 +2922,7 @@
 	const double fraction = 1.0 - ((cy - line->y_position()) / (double)line->height());
 
 	line->start_drag (0, drag_info.grab_frame, fraction);
-	
+
 	set_verbose_canvas_cursor (line->get_verbose_cursor_string (fraction),
 				   drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20);
 	show_verbose_canvas_cursor ();
@@ -2959,7 +2972,7 @@
 	}
 
 	line->line_drag (current_line_drag_info.before, current_line_drag_info.after, fraction, push);
-	
+
 	set_verbose_canvas_cursor_text (line->get_verbose_cursor_string (fraction));
 }
 
@@ -2999,13 +3012,13 @@
 	if (tv && tv->is_track()) {
 		speed = tv->get_diskstream()->speed();
 	}
-	
+
 	drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed);
 	drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
 	drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
 	// we want a move threshold
 	drag_info.want_move_threshold = true;
-	
+
 	show_verbose_time_cursor (drag_info.last_frame_position, 10);
 
 	begin_reversible_command (_("move region(s)"));
@@ -3033,7 +3046,7 @@
 
 	drag_info.copy = true;
 	drag_info.item = item;
-	drag_info.data = clicked_regionview;	
+	drag_info.data = clicked_regionview;
 
 	start_grab(event);
 
@@ -3044,7 +3057,7 @@
 	if (rtv && rtv->is_track()) {
 		speed = rtv->get_diskstream()->speed();
 	}
-	
+
 	drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
 	drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed);
 	drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
@@ -3077,14 +3090,14 @@
 	if (tv && tv->is_track()) {
 		speed = tv->get_diskstream()->speed();
 	}
-	
+
 	drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed);
 	drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
 	drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
 	// we want a move threshold
 	drag_info.want_move_threshold = true;
 	drag_info.brushing = true;
-	
+
 	begin_reversible_command (_("Drag region brush"));
 }
 
@@ -3098,7 +3111,7 @@
 		/* duplicate the region(s) */
 
 		vector<RegionView*> new_regionviews;
-		
+
 		for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
 
 			RegionView* rv;
@@ -3131,7 +3144,7 @@
 		selection->set (new_regionviews);
 
 		/* reset drag_info data to reflect the fact that we are dragging the copies */
-		
+
 		drag_info.data = new_regionviews.front();
 
 		swap_grab (new_regionviews.front()->get_canvas_group (), 0, event->motion.time);
@@ -3149,15 +3162,15 @@
 	/* The region motion is only processed if the pointer is over
 	   an audio track.
 	*/
-	
+
 	if (!(*tv) || !(*tv)->is_track()) {
-		/* To make sure we hide the verbose canvas cursor when the mouse is 
-		   not held over and audiotrack. 
+		/* To make sure we hide the verbose canvas cursor when the mouse is
+		   not held over and audiotrack.
 		*/
 		hide_verbose_canvas_cursor ();
 		return false;
 	}
-	
+
 	return true;
 }
 
@@ -3171,7 +3184,7 @@
 Editor::region_drag_splice_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 {
 	RouteTimeAxisView* tv;
-	
+
 	if (!check_region_drag_possible (&tv)) {
 		return;
 	}
@@ -3209,7 +3222,7 @@
 
 		if (!playlist->region_is_shuffle_constrained ((*i)->region())) {
 			continue;
-		} 
+		}
 
 		if (dir > 0) {
 			if (drag_info.current_pointer_frame < (*i)->region()->last_frame() + 1) {
@@ -3221,7 +3234,7 @@
 			}
 		}
 
-		
+
 		playlist->shuffle ((*i)->region(), dir);
 
 		drag_info.grab_x = drag_info.current_pointer_x;
@@ -3238,7 +3251,7 @@
 {
 	double x_delta;
 	double y_delta = 0;
-	RegionView* rv = reinterpret_cast<RegionView*> (drag_info.data); 
+	RegionView* rv = reinterpret_cast<RegionView*> (drag_info.data);
 	nframes_t pending_region_position = 0;
 	int32_t pointer_y_span = 0, canvas_pointer_y_span = 0, original_pointer_order;
 	int32_t visible_y_high = 0, visible_y_low = 512;  //high meaning higher numbered.. not the height on the screen
@@ -3254,10 +3267,10 @@
 	}
 
 	original_pointer_order = drag_info.last_trackview->order;
-		
+
 	/************************************************************
 	     Y-Delta Computation
-	************************************************************/	
+	************************************************************/
 
 	if (drag_info.brushing) {
 		clamp_y_axis = true;
@@ -3277,33 +3290,33 @@
 			tracklist_timeview = (*i);
 			RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(tracklist_timeview);
 			TimeAxisView::Children children_list;
-	      
+
 			/* zeroes are audio tracks. ones are other types. */
-	      
+
 			if (!rtv2->hidden()) {
-				
+
 				if (visible_y_high < rtv2->order) {
 					visible_y_high = rtv2->order;
 				}
 				if (visible_y_low > rtv2->order) {
 					visible_y_low = rtv2->order;
 				}
-		
-				if (!rtv2->is_track()) {		  		  
+
+				if (!rtv2->is_track()) {
 					tracks = tracks |= (0x01 << rtv2->order);
 				}
-	
+
 				height_list[rtv2->order] = (*i)->height;
 				children = 1;
 				if ((children_list = rtv2->get_child_list()).size() > 0) {
-					for (TimeAxisView::Children::iterator j = children_list.begin(); j != children_list.end(); ++j) { 
+					for (TimeAxisView::Children::iterator j = children_list.begin(); j != children_list.end(); ++j) {
 						tracks = tracks |= (0x01 << (rtv2->order + children));
-						height_list[rtv2->order + children] =  (*j)->height;		    
+						height_list[rtv2->order + children] =  (*j)->height;
 						numtracks++;
-						children++;	
+						children++;
 					}
 				}
-				numtracks++;	    
+				numtracks++;
 			}
 		}
 		/* find the actual span according to the canvas */
@@ -3335,67 +3348,67 @@
 			TimeAxisView* tvp2 = trackview_by_y_position (iy1);
 			RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
 
-			if (rtv2->order != original_pointer_order) {	
-				/* this isn't the pointer track */	
+			if (rtv2->order != original_pointer_order) {
+				/* this isn't the pointer track */
 
 				if (canvas_pointer_y_span > 0) {
 
 					/* moving up the canvas */
 					if ((rtv2->order - canvas_pointer_y_span) >= visible_y_low) {
-	
+
 						int32_t visible_tracks = 0;
 						while (visible_tracks < canvas_pointer_y_span ) {
 							visible_tracks++;
-		  
+
 							while (height_list[rtv2->order - (visible_tracks - n)] == 0) {
 								/* we're passing through a hidden track */
 								n--;
-							}		  
+							}
 						}
-		 
-						if (tracks[rtv2->order - (canvas_pointer_y_span - n)] != 0x00) {		  
+
+						if (tracks[rtv2->order - (canvas_pointer_y_span - n)] != 0x00) {
 							clamp_y_axis = true;
 						}
-		    
+
 					} else {
 						clamp_y_axis = true;
-					}		  
-		  
+					}
+
 				} else if (canvas_pointer_y_span < 0) {
 
 					/*moving down the canvas*/
 
 					if ((rtv2->order - (canvas_pointer_y_span - n)) <= visible_y_high) { // we will overflow
-		    
-		    
+
+
 						int32_t visible_tracks = 0;
-		    
+
 						while (visible_tracks > canvas_pointer_y_span ) {
 							visible_tracks--;
-		      
-							while (height_list[rtv2->order - (visible_tracks - n)] == 0) {		   
+
+							while (height_list[rtv2->order - (visible_tracks - n)] == 0) {
 								n++;
-							}		 
+							}
 						}
 						if (  tracks[rtv2->order - ( canvas_pointer_y_span - n)] != 0x00) {
 							clamp_y_axis = true;
-			    
+
 						}
 					} else {
-			  
+
 						clamp_y_axis = true;
 					}
-				}		
-		  
+				}
+
 			} else {
-		      
+
 				/* this is the pointer's track */
-				if ((rtv2->order - pointer_y_span) > visible_y_high) { // we will overflow 
+				if ((rtv2->order - pointer_y_span) > visible_y_high) { // we will overflow
 					clamp_y_axis = true;
 				} else if ((rtv2->order - pointer_y_span) < visible_y_low) { // we will underflow
 					clamp_y_axis = true;
 				}
-			}	      
+			}
 			if (clamp_y_axis) {
 				break;
 			}
@@ -3403,13 +3416,13 @@
 
 	} else  if (drag_info.last_trackview == tv) {
 		clamp_y_axis = true;
-	}	  
+	}
 
   y_axis_done:
 	if (!clamp_y_axis) {
-		drag_info.last_trackview = tv;	      
+		drag_info.last_trackview = tv;
 	}
-	  
+
 	/************************************************************
 	    X DELTA COMPUTATION
 	************************************************************/
@@ -3437,27 +3450,27 @@
 
 				/* we snap if the snap modifier is not enabled.
 				 */
-	    
+
 				if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
-					snap_to (sync_frame);	
+					snap_to (sync_frame);
 				}
-	    
+
 				pending_region_position = rv->region()->adjust_to_sync (sync_frame);
 
 			} else {
 				pending_region_position = drag_info.last_frame_position;
 			}
-	    
+
 		} else {
 			pending_region_position = 0;
 		}
-	  
+
 		if (pending_region_position > max_frames - rv->region()->length()) {
 			pending_region_position = drag_info.last_frame_position;
 		}
-	  
+
 		// printf ("3: pending_region_position= %lu    %lu\n", pending_region_position, drag_info.last_frame_position );
-	  
+
 		bool x_move_allowed = ( !drag_info.x_constrained && (Config->get_edit_mode() != Lock)) || ( drag_info.x_constrained && (Config->get_edit_mode() == Lock)) ;
 		if ( pending_region_position != drag_info.last_frame_position && x_move_allowed ) {
 
@@ -3472,7 +3485,7 @@
 			}
 
 			drag_info.last_frame_position = pending_region_position;
-	    
+
 		} else {
 			x_delta = 0;
 		}
@@ -3482,7 +3495,7 @@
 
 		x_delta = 0;
 	}
-	
+
 	/*************************************************************
 	    PREPARE TO MOVE
 	************************************************************/
@@ -3492,7 +3505,7 @@
 		   trackviews. nothing to do.
 		*/
 		return;
-	} 
+	}
 
 
 	if (x_delta < 0) {
@@ -3501,7 +3514,7 @@
 			RegionView* rv2 = (*i);
 
 			// If any regionview is at zero, we need to know so we can stop further leftward motion.
-			
+
 			double ix1, ix2, iy1, iy2;
 			rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
 			rv2->get_canvas_group()->i2w (ix1, iy1);
@@ -3514,7 +3527,7 @@
 	}
 
 	/*************************************************************
-	    MOTION								      
+	    MOTION
 	************************************************************/
 
 	bool do_move;
@@ -3533,9 +3546,9 @@
 
 		pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
 		const list<RegionView*>& layered_regions = selection->regions.by_layer();
-		
+
 		for (list<RegionView*>::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) {
-	    
+
 			RegionView* rv = (*i);
 			double ix1, ix2, iy1, iy2;
 			int32_t temp_pointer_y_span = pointer_y_span;
@@ -3554,44 +3567,44 @@
 			if ((pointer_y_span != 0) && !clamp_y_axis) {
 				y_delta = 0;
 				int32_t x = 0;
-				for (j = height_list.begin(); j!= height_list.end(); j++) {	
+				for (j = height_list.begin(); j!= height_list.end(); j++) {
 					if (x == canvas_rtv->order) {
 						/* we found the track the region is on */
 						if (x != original_pointer_order) {
 							/*this isn't from the same track we're dragging from */
 							temp_pointer_y_span = canvas_pointer_y_span;
-						}		  
+						}
 						while (temp_pointer_y_span > 0) {
 							/* we're moving up canvas-wise,
 							   so  we need to find the next track height
 							*/
-							if (j != height_list.begin()) {		  
+							if (j != height_list.begin()) {
 								j--;
 							}
-							if (x != original_pointer_order) { 
-								/* we're not from the dragged track, so ignore hidden tracks. */	      
+							if (x != original_pointer_order) {
+								/* we're not from the dragged track, so ignore hidden tracks. */
 								if ((*j) == 0) {
 									temp_pointer_y_span++;
 								}
-							}	   
-							y_delta -= (*j);	
-							temp_pointer_y_span--;	
+							}
+							y_delta -= (*j);
+							temp_pointer_y_span--;
 						}
-						while (temp_pointer_y_span < 0) {		  
+						while (temp_pointer_y_span < 0) {
 							y_delta += (*j);
-							if (x != original_pointer_order) { 
+							if (x != original_pointer_order) {
 								if ((*j) == 0) {
 									temp_pointer_y_span--;
 								}
-							}	   
-		    
-							if (j != height_list.end()) {		      
+							}
+
+							if (j != height_list.end()) {
 								j++;
 							}
 							temp_pointer_y_span++;
 						}
 						/* find out where we'll be when we move and set height accordingly */
-		  
+
 						tvp2 = trackview_by_y_position (iy1 + y_delta);
 						temp_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
 						rv->set_y_position_and_height (0, temp_rtv->height);
@@ -3599,20 +3612,20 @@
 						/*   if you un-comment the following, the region colours will follow the track colours whilst dragging,
 						     personally, i think this can confuse things, but never mind.
 						*/
-		  		  
+
 						//const GdkColor& col (temp_rtv->view->get_region_color());
 						//rv->set_color (const_cast<GdkColor&>(col));
-						break;		
+						break;
 					}
 					x++;
 				}
 			}
-	  
-			/* prevent the regionview from being moved to before 
+
+			/* prevent the regionview from being moved to before
 			   the zero position on the canvas.
 			*/
 			/* clamp */
-		
+
 			if (x_delta < 0) {
 				if (-x_delta > ix1) {
 					x_delta = -ix1;
@@ -3625,15 +3638,15 @@
 			if (drag_info.first_move) {
 
 				/* hide any dependent views */
-			
+
 				rv->get_time_axis_view().hide_dependent_views (*rv);
-			
+
 				/* this is subtle. raising the regionview itself won't help,
 				   because raise_to_top() just puts the item on the top of
 				   its parent's stack. so, we need to put the trackview canvas_display group
 				   on the top, since its parent is the whole canvas.
 				*/
-			
+
 				rv->get_canvas_group()->raise_to_top();
 				rv->get_time_axis_view().canvas_display->raise_to_top();
 				cursor_group->raise_to_top();
@@ -3644,7 +3657,7 @@
 			if (drag_info.brushing) {
 				mouse_brush_insert_region (rv, pending_region_position);
 			} else {
-				rv->move (x_delta, y_delta);			
+				rv->move (x_delta, y_delta);
 			}
 
 		} /* foreach region */
@@ -3659,7 +3672,7 @@
 	if (x_delta != 0 && !drag_info.brushing) {
 		show_verbose_time_cursor (drag_info.last_frame_position, 10);
 	}
-} 
+}
 
 void
 Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
@@ -3677,8 +3690,8 @@
 	list <sigc::connection > used_connections;
 	bool preserve_selection = false;
 
-	/* first_move is set to false if the regionview has been moved in the 
-	   motion handler. 
+	/* first_move is set to false if the regionview has been moved in the
+	   motion handler.
 	*/
 
 	if (drag_info.first_move) {
@@ -3689,8 +3702,8 @@
 	nocommit = false;
 
 	/* The regionview has been moved at some stage during the grab so we need
-	   to account for any mouse movement between this event and the last one. 
-	*/	
+	   to account for any mouse movement between this event and the last one.
+	*/
 
 	region_drag_motion_callback (item, event);
 
@@ -3701,7 +3714,7 @@
 
 	if (drag_info.brushing) {
 		/* all changes were made during motion event handlers */
-		
+
 		if (drag_info.copy) {
 			for (list<RegionView*>::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
 				copies.push_back (*i);
@@ -3718,13 +3731,13 @@
 	if (rtv && rtv->get_diskstream()) {
 		speed = rtv->get_diskstream()->speed();
 	}
-	
+
 	regionview_x_movement = (drag_info.last_frame_position != (nframes_t) (rvdi->region()->position()/speed));
 	regionview_y_movement = (drag_info.last_trackview != &rvdi->get_time_axis_view());
 
-	//printf ("last_frame: %s position is %lu  %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed); 
-	//printf ("last_rackview: %s \n", drag_info.last_trackview->name().c_str()); 
-	
+	//printf ("last_frame: %s position is %lu  %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed);
+	//printf ("last_rackview: %s \n", drag_info.last_trackview->name().c_str());
+
 	char* op_string;
 
 	if (drag_info.copy) {
@@ -3732,7 +3745,7 @@
 			op_string = _("fixed time region copy");
 		} else {
 			op_string = _("region copy");
-		} 
+		}
 	} else {
 		if (drag_info.x_constrained) {
 			op_string = _("fixed time region drag");
@@ -3746,15 +3759,15 @@
 	if (regionview_y_movement) {
 
 		/* moved to a different track. */
-		
+
 		vector<RegionView*> new_selection;
-		
+
 		for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) {
-			
-			RegionView* rv = (*i);	    
 
+			RegionView* rv = (*i);
+
 			double ix1, ix2, iy1, iy2;
-			
+
 			rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
 			rv->get_canvas_group()->i2w (ix1, iy1);
 
@@ -3762,20 +3775,20 @@
 
 			boost::shared_ptr<Playlist> from_playlist = rv->region()->playlist();
 			boost::shared_ptr<Playlist> to_playlist = rtv2->playlist();
-			
+
 			where = (nframes_t) (unit_to_frame (ix1) * speed);
 			boost::shared_ptr<Region> new_region (RegionFactory::create (rv->region()));
 
 			if (! to_playlist->frozen()) {
-				/* 
-				   we haven't seen this playlist before. 
-				   we want to freeze it because we don't want to relayer per-region. 
-				   its much better to do that just once if the playlist is large. 
+				/*
+				   we haven't seen this playlist before.
+				   we want to freeze it because we don't want to relayer per-region.
+				   its much better to do that just once if the playlist is large.
 				*/
 
 				/*
-				   connect so the selection is changed when the new regionview finally appears (after thaw). 
-				   keep track of it so we can disconnect later. 
+				   connect so the selection is changed when the new regionview finally appears (after thaw).
+				   keep track of it so we can disconnect later.
 				*/
 
 				sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view));
@@ -3784,31 +3797,31 @@
 				/* undo */
 				session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
 
-				/* remember used playlists so we can thaw them later */	
+				/* remember used playlists so we can thaw them later */
 				used_playlists.push_back(to_playlist);
 				to_playlist->freeze();
 			}
-			
+
 			/* undo the previous hide_dependent_views so that xfades don't
-			   disappear on copying regions 
+			   disappear on copying regions
 			*/
 
 			rv->get_time_axis_view().reveal_dependent_views (*rv);
 
 			if (!drag_info.copy) {
-				
+
 				/* the region that used to be in the old playlist is not
 				   moved to the new one - we make a copy of it. as a result,
 				   any existing editor for the region should no longer be
 				   visible.
-				*/ 
-	    
+				*/
+
 				rv->hide_region_editor();
 				rv->fake_set_opaque (false);
 
-				session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));	
+				session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));
 				from_playlist->remove_region ((rv->region()));
-				session->add_command (new MementoCommand<Playlist>(*from_playlist, 0, &from_playlist->get_state()));	
+				session->add_command (new MementoCommand<Playlist>(*from_playlist, 0, &from_playlist->get_state()));
 
 			} else {
 
@@ -3819,12 +3832,12 @@
 
 			latest_regionviews.clear ();
 			sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
-			session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));	
+			session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
 
 			to_playlist->add_region (new_region, where);
-			session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));	
+			session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));
 			c.disconnect ();
-							      
+
 			if (!latest_regionviews.empty()) {
 				new_selection.insert (new_selection.end(), latest_regionviews.begin(), latest_regionviews.end());
 			}
@@ -3852,9 +3865,9 @@
 			} else {
 				if (selection->regions.empty()) {
 					break;
-				} else { 
+				} else {
 				  /*
-				    XXX see above .. but we just froze the playlists.. we have to keep iterating, right? 
+				    XXX see above .. but we just froze the playlists.. we have to keep iterating, right?
 				  */
 
 				  //i = selection->regions.by_layer().begin();
@@ -3885,17 +3898,17 @@
 				if (from_rtv && from_rtv->get_diskstream()) {
 					ownspeed = from_rtv->get_diskstream()->speed();
 				}
-				
+
 				/* base the new region position on the current position of the regionview.*/
-				
+
 				double ix1, ix2, iy1, iy2;
-				
+
 				rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
 				rv->get_canvas_group()->i2w (ix1, iy1);
 				where = (nframes_t) (unit_to_frame (ix1) * ownspeed);
-				
+
 			} else {
-				
+
 				where = rv->region()->position();
 			}
 
@@ -3903,7 +3916,7 @@
 				sigc::connection c = from_rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view));
 				used_connections.push_back (c);
 
-				/* add the undo */	
+				/* add the undo */
 				session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
 
 				used_playlists.push_back(to_playlist);
@@ -3934,7 +3947,7 @@
 					rtv->reveal_dependent_views (*latest_regionviews.front());
 					selection->add (latest_regionviews);
 				}
-				
+
 			} else {
 
 				/* just change the model */
@@ -3967,7 +3980,7 @@
 	}
 
   out:
-	
+
 	if (!nocommit) {
 		commit_reversible_command ();
 	}
@@ -3977,7 +3990,7 @@
 	}
 }
 
-	
+
 void
 Editor::create_region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 {
@@ -3989,7 +4002,7 @@
 
 		// TODO: resize region-create-drag region view here
 	}
-} 
+}
 
 void
 Editor::create_region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
@@ -4000,7 +4013,7 @@
 
 	const boost::shared_ptr<MidiDiskstream> diskstream =
 		boost::dynamic_pointer_cast<MidiDiskstream>(mtv->view()->trackview().track()->diskstream());
-	
+
 	if (!diskstream) {
 		warning << "Cannot create non-MIDI region" << endl;
 		return;
@@ -4017,9 +4030,9 @@
 		double length = floor (m.frames_per_bar(t, session->frame_rate()));
 
 		boost::shared_ptr<Source> src = session->create_midi_source_for_session(*diskstream.get());
-				
+
 		mtv->playlist()->add_region (boost::dynamic_pointer_cast<MidiRegion>
-					     (RegionFactory::create(src, 0, (nframes_t) length, 
+					     (RegionFactory::create(src, 0, (nframes_t) length,
 								    PBD::basename_nosuffix(src->name()))), start);
 		XMLNode &after = mtv->playlist()->get_state();
 		session->add_command(new MementoCommand<Playlist>(*mtv->playlist().get(), &before, &after));
@@ -4037,7 +4050,7 @@
 	/* Either add to or set the set the region selection, unless
 	   this is an alignment click (control used)
 	*/
-	
+
 	if (Keyboard::modifier_state_contains (event->state, Keyboard::PrimaryModifier)) {
 		TimeAxisView* tv = &rv.get_time_axis_view();
 		RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(tv);
@@ -4051,15 +4064,15 @@
 		if (where >= 0) {
 
 			if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
-				
+
 				align_region (rv.region(), SyncPoint, (nframes_t) (where * speed));
-				
+
 			} else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
-				
+
 				align_region (rv.region(), End, (nframes_t) (where * speed));
-				
+
 			} else {
-				
+
 				align_region (rv.region(), Start, (nframes_t) (where * speed));
 			}
 		}
@@ -4067,7 +4080,7 @@
 }
 
 void
-Editor::show_verbose_time_cursor (nframes_t frame, double offset, double xpos, double ypos) 
+Editor::show_verbose_time_cursor (nframes_t frame, double offset, double xpos, double ypos)
 {
 	char buf[128];
 	SMPTE::Time smpte;
@@ -4085,7 +4098,7 @@
 		session->bbt_time (frame, bbt);
 		snprintf (buf, sizeof (buf), "%02" PRIu32 "|%02" PRIu32 "|%02" PRIu32, bbt.bars, bbt.beats, bbt.ticks);
 		break;
-		
+
 	case AudioClock::SMPTE:
 		session->smpte_time (frame, smpte);
 		snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%02" PRId32 ":%02" PRId32, smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
@@ -4117,7 +4130,7 @@
 }
 
 void
-Editor::show_verbose_duration_cursor (nframes_t start, nframes_t end, double offset, double xpos, double ypos) 
+Editor::show_verbose_duration_cursor (nframes_t start, nframes_t end, double offset, double xpos, double ypos)
 {
 	char buf[128];
 	SMPTE::Time smpte;
@@ -4155,10 +4168,10 @@
 			ebbt.beats--;
 			ebbt.ticks = int(Meter::ticks_per_beat) + ebbt.ticks - sbbt.ticks;
 		}
-		
+
 		snprintf (buf, sizeof (buf), "%02" PRIu32 "|%02" PRIu32 "|%02" PRIu32, ebbt.bars, ebbt.beats, ebbt.ticks);
 		break;
-		
+
 	case AudioClock::SMPTE:
 		session->smpte_duration (end - start, smpte);
 		snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%02" PRId32 ":%02" PRId32, smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
@@ -4220,7 +4233,7 @@
 	}
 
 	/* XXX fix me one day to use all new regions */
-	
+
 	boost::shared_ptr<Region> region (new_regions.front());
 
 	/* add it to the current stream/playlist.
@@ -4229,11 +4242,11 @@
 	   catch the signal it sends when it creates the regionview to
 	   set the regionview we want to then drag.
 	*/
-	
+
 	latest_regionviews.clear();
 	sigc::connection c = clicked_routeview->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
-	
-	/* A selection grab currently creates two undo/redo operations, one for 
+
+	/* A selection grab currently creates two undo/redo operations, one for
 	   creating the new region and another for moving it.
 	*/
 
@@ -4247,30 +4260,30 @@
 	session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
 
 	commit_reversible_command ();
-	
+
 	c.disconnect ();
-	
+
 	if (latest_regionviews.empty()) {
 		/* something went wrong */
 		return;
 	}
 
 	/* we need to deselect all other regionviews, and select this one
-	   i'm ignoring undo stuff, because the region creation will take care of it 
+	   i'm ignoring undo stuff, because the region creation will take care of it
 	*/
 	selection->set (latest_regionviews);
-	
+
 	drag_info.item = latest_regionviews.front()->get_canvas_group();
 	drag_info.data = latest_regionviews.front();
 	drag_info.motion_callback = &Editor::region_drag_motion_callback;
 	drag_info.finished_callback = &Editor::region_drag_finished_callback;
 
 	start_grab (event);
-	
+
 	drag_info.last_trackview = clicked_axisview;
 	drag_info.last_frame_position = latest_regionviews.front()->region()->position();
 	drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
-	
+
 	show_verbose_time_cursor (drag_info.last_frame_position, 10);
 }
 
@@ -4282,7 +4295,7 @@
 	}
 	selection->clear ();
 	clicked_selection = 0;
-}	
+}
 
 void
 Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, SelectionOp op)
@@ -4313,32 +4326,32 @@
 	case SelectionStartTrim:
 		if (clicked_axisview) {
 			clicked_axisview->order_selection_trims (item, true);
-		} 
+		}
 		start_grab (event, trimmer_cursor);
 		start = selection->time[clicked_selection].start;
-		drag_info.pointer_frame_offset = drag_info.grab_frame - start;	
+		drag_info.pointer_frame_offset = drag_info.grab_frame - start;
 		break;
-		
+
 	case SelectionEndTrim:
 		if (clicked_axisview) {
 			clicked_axisview->order_selection_trims (item, false);
 		}
 		start_grab (event, trimmer_cursor);
 		end = selection->time[clicked_selection].end;
-		drag_info.pointer_frame_offset = drag_info.grab_frame - end;	
+		drag_info.pointer_frame_offset = drag_info.grab_frame - end;
 		break;
 
 	case SelectionMove:
 		start = selection->time[clicked_selection].start;
 		start_grab (event);
-		drag_info.pointer_frame_offset = drag_info.grab_frame - start;	
+		drag_info.pointer_frame_offset = drag_info.grab_frame - start;
 		break;
 	}
 
 	if (selection_op == SelectionMove) {
-		show_verbose_time_cursor(start, 10);	
+		show_verbose_time_cursor(start, 10);
 	} else {
-		show_verbose_time_cursor(drag_info.current_pointer_frame, 10);	
+		show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
 	}
 }
 
@@ -4355,24 +4368,24 @@
 	} else {
 		pending_position = 0;
 	}
-	
+
 	if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
 		snap_to (pending_position);
 	}
 
-	/* only alter selection if the current frame is 
+	/* only alter selection if the current frame is
 	   different from the last frame position (adjusted)
 	 */
-	
+
 	if (pending_position == drag_info.last_pointer_frame) return;
-	
+
 	switch (selection_op) {
 	case CreateSelection:
-		
+
 		if (drag_info.first_move) {
 			snap_to (drag_info.grab_frame);
 		}
-		
+
 		if (pending_position < drag_info.grab_frame) {
 			start = pending_position;
 			end = drag_info.grab_frame;
@@ -4380,15 +4393,15 @@
 			end = pending_position;
 			start = drag_info.grab_frame;
 		}
-		
+
 		/* first drag: Either add to the selection
 		   or create a new selection->
 		*/
-		
+
 		if (drag_info.first_move) {
-			
+
 			begin_reversible_command (_("range selection"));
-			
+
 			if (drag_info.copy) {
 				/* adding to the selection */
 				clicked_selection = selection->add (start, end);
@@ -4397,15 +4410,15 @@
 				/* new selection-> */
 				clicked_selection = selection->set (clicked_axisview, start, end);
 			}
-		} 
+		}
 		break;
-		
+
 	case SelectionStartTrim:
-		
+
 		if (drag_info.first_move) {
 			begin_reversible_command (_("trim selection start"));
 		}
-		
+
 		start = selection->time[clicked_selection].start;
 		end = selection->time[clicked_selection].end;
 
@@ -4415,13 +4428,13 @@
 			start = pending_position;
 		}
 		break;
-		
+
 	case SelectionEndTrim:
-		
+
 		if (drag_info.first_move) {
 			begin_reversible_command (_("trim selection end"));
 		}
-		
+
 		start = selection->time[clicked_selection].start;
 		end = selection->time[clicked_selection].end;
 
@@ -4430,28 +4443,28 @@
 		} else {
 			end = pending_position;
 		}
-		
+
 		break;
-		
+
 	case SelectionMove:
-		
+
 		if (drag_info.first_move) {
 			begin_reversible_command (_("move selection"));
 		}
-		
+
 		start = selection->time[clicked_selection].start;
 		end = selection->time[clicked_selection].end;
-		
+
 		length = end - start;
-		
+
 		start = pending_position;
 		snap_to (start);
-		
+
 		end = start + length;
-		
+
 		break;
 	}
-	
+
 	if (event->button.x >= horizontal_adjustment.get_value() + canvas_width) {
 		start_canvas_autoscroll (1);
 	}
@@ -4464,9 +4477,9 @@
 	drag_info.first_move = false;
 
 	if (selection_op == SelectionMove) {
-		show_verbose_time_cursor(start, 10);	
+		show_verbose_time_cursor(start, 10);
 	} else {
-		show_verbose_time_cursor(pending_position, 10);	
+		show_verbose_time_cursor(pending_position, 10);
 	}
 }
 
@@ -4487,7 +4500,7 @@
 
 			selection->clear_time();
 
-		} 
+		}
 	}
 
 	/* XXX what happens if its a music selection? */
@@ -4505,7 +4518,7 @@
 	if (tv && tv->is_track()) {
 		speed = tv->get_diskstream()->speed();
 	}
-	
+
 	nframes_t region_start = (nframes_t) (clicked_regionview->region()->position() / speed);
 	nframes_t region_end = (nframes_t) (clicked_regionview->region()->last_frame() / speed);
 	nframes_t region_length = (nframes_t) (clicked_regionview->region()->length() / speed);
@@ -4516,7 +4529,7 @@
 	drag_info.finished_callback = &Editor::trim_finished_callback;
 
 	start_grab (event, trimmer_cursor);
-	
+
 	if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
 		trim_op = ContentsTrim;
 	} else {
@@ -4532,13 +4545,13 @@
 
 	switch (trim_op) {
 	case StartTrim:
-		show_verbose_time_cursor(region_start, 10);	
+		show_verbose_time_cursor(region_start, 10);
 		break;
 	case EndTrim:
-		show_verbose_time_cursor(region_end, 10);	
+		show_verbose_time_cursor(region_end, 10);
 		break;
 	case ContentsTrim:
-		show_verbose_time_cursor(drag_info.current_pointer_frame, 10);	
+		show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
 		break;
 	}
 }
@@ -4552,9 +4565,9 @@
 	bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier());
 
 	/* snap modifier works differently here..
-	   its' current state has to be passed to the 
-	   various trim functions in order to work properly 
-	*/ 
+	   its' current state has to be passed to the
+	   various trim functions in order to work properly
+	*/
 
 	double speed = 1.0;
 	TimeAxisView* tvp = clicked_axisview;
@@ -4564,7 +4577,7 @@
 	if (tv && tv->is_track()) {
 		speed = tv->get_diskstream()->speed();
 	}
-	
+
 	if (drag_info.last_pointer_frame > drag_info.current_pointer_frame) {
 		left_direction = true;
 	} else {
@@ -4580,7 +4593,7 @@
 	}
 
 	if (drag_info.first_move) {
-	
+
 		string trim_type;
 
 		switch (trim_op) {
@@ -4600,7 +4613,7 @@
 		for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
 			(*i)->fake_set_opaque(false);
 			(*i)->region()->freeze ();
-		
+
 			AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
 			if (arv)
 				arv->temporarily_hide_envelope ();
@@ -4620,7 +4633,7 @@
 		frame_delta = (drag_info.current_pointer_frame - drag_info.last_pointer_frame);
 	}
 
-	switch (trim_op) {		
+	switch (trim_op) {
 	case StartTrim:
 		if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region()->first_frame()/speed)) {
 			break;
@@ -4630,7 +4643,7 @@
 			}
 			break;
 		}
-		
+
 	case EndTrim:
 		if ((left_direction == true) && (drag_info.current_pointer_frame > (nframes_t) (rv->region()->last_frame()/speed))) {
 			break;
@@ -4640,7 +4653,7 @@
 			}
 			break;
 		}
-		
+
 	case ContentsTrim:
 		{
 			bool swap_direction = false;
@@ -4648,7 +4661,7 @@
 			if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
 				swap_direction = true;
 			}
-			
+
 			for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin();
 			     i != selection->regions.by_layer().end(); ++i)
 			{
@@ -4660,13 +4673,13 @@
 
 	switch (trim_op) {
 	case StartTrim:
-		show_verbose_time_cursor((nframes_t) (rv->region()->position()/speed), 10);	
+		show_verbose_time_cursor((nframes_t) (rv->region()->position()/speed), 10);
 		break;
 	case EndTrim:
-		show_verbose_time_cursor((nframes_t) (rv->region()->last_frame()/speed), 10);	
+		show_verbose_time_cursor((nframes_t) (rv->region()->last_frame()/speed), 10);
 		break;
 	case ContentsTrim:
-		show_verbose_time_cursor(drag_info.current_pointer_frame, 10);	
+		show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
 		break;
 	}
 
@@ -4692,7 +4705,7 @@
 	if (tv && tv->is_track()) {
 		speed = tv->get_diskstream()->speed();
 	}
-	
+
 	if (left_direction) {
 		if (swap_direction) {
 			new_bound = (nframes_t) (region->position()/speed) + frame_delta;
@@ -4710,14 +4723,14 @@
 	if (obey_snap) {
 		snap_to (new_bound);
 	}
-	region->trim_start ((nframes_t) (new_bound * speed), this);	
+	region->trim_start ((nframes_t) (new_bound * speed), this);
 	rv.region_changed (StartChanged);
 }
 
 void
 Editor::single_start_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool obey_snap)
 {
-	boost::shared_ptr<Region> region (rv.region());	
+	boost::shared_ptr<Region> region (rv.region());
 
 	if (region->locked()) {
 		return;
@@ -4732,7 +4745,7 @@
 	if (tv && tv->is_track()) {
 		speed = tv->get_diskstream()->speed();
 	}
-	
+
 	if (left_direction) {
 		new_bound = (nframes_t) (region->position()/speed) - frame_delta;
 	} else {
@@ -4740,7 +4753,7 @@
 	}
 
 	if (obey_snap) {
-		snap_to (new_bound, (left_direction ? 0 : 1));	
+		snap_to (new_bound, (left_direction ? 0 : 1));
 	}
 
 	region->trim_front ((nframes_t) (new_bound * speed), this);
@@ -4766,7 +4779,7 @@
 	if (tv && tv->is_track()) {
 		speed = tv->get_diskstream()->speed();
 	}
-	
+
 	if (left_direction) {
 		new_bound = (nframes_t) ((region->last_frame() + 1)/speed) - frame_delta;
 	} else {
@@ -4779,17 +4792,17 @@
 	region->trim_end ((nframes_t) (new_bound * speed), this);
 	rv.region_changed (LengthChanged);
 }
-	
+
 void
 Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
 {
 	if (!drag_info.first_move) {
 		trim_motion_callback (item, event);
-		
+
 		if (!selection->selected (clicked_regionview)) {
-			thaw_region_after_trim (*clicked_regionview);		
+			thaw_region_after_trim (*clicked_regionview);
 		} else {
-			
+
 			for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin();
 			     i != selection->regions.by_layer().end(); ++i)
 			{
@@ -4797,12 +4810,12 @@
 				(*i)->fake_set_opaque (true);
 			}
 		}
-		
+
 		for (set<boost::shared_ptr<Playlist> >::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) {
 			(*p)->thaw ();
 			session->add_command (new MementoCommand<Playlist>(*(*p).get(), 0, &(*p)->get_state()));
 		}
-		
+
 		motion_frozen_playlists.clear ();
 
 		commit_reversible_command();
@@ -4836,7 +4849,7 @@
 				if (!(*i)->region()->locked()) {
 					boost::shared_ptr<Playlist> pl = (*i)->region()->playlist();
 					XMLNode &before = pl->get_state();
-					(*i)->region()->trim_front (new_bound, this);	
+					(*i)->region()->trim_front (new_bound, this);
 					XMLNode &after = pl->get_state();
 					session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after));
 				}
@@ -4847,21 +4860,21 @@
 			if (!rv->region()->locked()) {
 				boost::shared_ptr<Playlist> pl = rv->region()->playlist();
 				XMLNode &before = pl->get_state();
-				rv->region()->trim_front (new_bound, this);	
+				rv->region()->trim_front (new_bound, this);
 				XMLNode &after = pl->get_state();
 				session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after));
 			}
 		}
 
 		commit_reversible_command();
-	
+
 		break;
 	case 2:
 		trim_op = EndTrim;
 		begin_reversible_command (_("End point trim"));
 
 		if (selection->selected (rv)) {
-			
+
 			for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i)
 			{
 				if (!(*i)->region()->locked()) {
@@ -4885,7 +4898,7 @@
 		}
 
 		commit_reversible_command();
-	
+
 		break;
 	default:
 		break;
@@ -4921,7 +4934,7 @@
 		/*NOTREACHED*/
 	}
 
-	Location* location = find_location_from_marker (marker, is_start);	
+	Location* location = find_location_from_marker (marker, is_start);
 	location->set_hidden (true, this);
 }
 
@@ -4942,12 +4955,12 @@
 	if (!temp_location) {
 		temp_location = new Location;
 	}
-	
+
 	switch (op) {
 	case CreateRangeMarker:
 	case CreateTransportMarker:
 	case CreateCDMarker:
-	
+
 		if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
 			drag_info.copy = true;
 		} else {
@@ -4957,8 +4970,8 @@
 		break;
 	}
 
-	show_verbose_time_cursor(drag_info.current_pointer_frame, 10);	
-	
+	show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
+
 }
 
 void
@@ -4983,17 +4996,17 @@
 		return;
 		break;
 	}
-	
+
 	if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
 		snap_to (drag_info.current_pointer_frame);
 	}
 
-	/* only alter selection if the current frame is 
+	/* only alter selection if the current frame is
 	   different from the last frame position.
 	 */
-	
+
 	if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) return;
-	
+
 	switch (range_marker_op) {
 	case CreateRangeMarker:
 	case CreateTransportMarker:
@@ -5001,7 +5014,7 @@
 		if (drag_info.first_move) {
 			snap_to (drag_info.grab_frame);
 		}
-		
+
 		if (drag_info.current_pointer_frame < drag_info.grab_frame) {
 			start = drag_info.current_pointer_frame;
 			end = drag_info.grab_frame;
@@ -5009,29 +5022,29 @@
 			end = drag_info.current_pointer_frame;
 			start = drag_info.grab_frame;
 		}
-		
+
 		/* first drag: Either add to the selection
 		   or create a new selection.
 		*/
-		
+
 		if (drag_info.first_move) {
-			
+
 			temp_location->set (start, end);
-			
+
 			crect->show ();
 
 			update_marker_drag_item (temp_location);
 			range_marker_drag_rect->show();
 			range_marker_drag_rect->raise_to_top();
-			
-		} 
-		break;		
+
+		}
+		break;
 	}
-	
+
 	if (event->button.x >= horizontal_adjustment.get_value() + canvas_width) {
 		start_canvas_autoscroll (1);
 	}
-	
+
 	if (start != end) {
 		temp_location->set (start, end);
 
@@ -5046,8 +5059,8 @@
 	drag_info.last_pointer_frame = drag_info.current_pointer_frame;
 	drag_info.first_move = false;
 
-	show_verbose_time_cursor(drag_info.current_pointer_frame, 10);	
-	
+	show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
+
 }
 
 void
@@ -5056,7 +5069,7 @@
 	Location * newloc = 0;
 	string rangename;
 	int flags;
-	
+
 	if (!drag_info.first_move) {
 		drag_range_markerbar_op (item, event);
 
@@ -5080,7 +5093,7 @@
 			XMLNode &after = session->locations()->get_state();
 			session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
 			commit_reversible_command ();
-			
+
 			range_marker_drag_rect->hide();
 			break;
 		    }
@@ -5088,7 +5101,7 @@
 		case CreateTransportMarker:
 			// popup menu to pick loop or punch
 			new_transport_marker_context_menu (&event->button, item);
-			
+
 			break;
 		}
 	} else {
@@ -5101,7 +5114,7 @@
 
 			start = session->locations()->first_mark_before (drag_info.grab_frame);
 			end = session->locations()->first_mark_after (drag_info.grab_frame);
-			
+
 			if (end == max_frames) {
 				end = session->current_end_frame ();
 			}
@@ -5124,7 +5137,7 @@
 			default:
 				break;
 			}
-		} 
+		}
 	}
 
 	stop_canvas_autoscroll ();
@@ -5152,12 +5165,12 @@
 
 	if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
 		snap_to (drag_info.current_pointer_frame);
-		
+
 		if (drag_info.first_move) {
 			snap_to (drag_info.grab_frame);
 		}
 	}
-		
+
 	if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) return;
 
 	/* base start and end on initial click position */
@@ -5168,7 +5181,7 @@
 		end = drag_info.current_pointer_frame;
 		start = drag_info.grab_frame;
 	}
-	
+
 	if (start != end) {
 
 		if (drag_info.first_move) {
@@ -5190,12 +5203,12 @@
 {
 	if (!drag_info.first_move) {
 		drag_mouse_zoom (item, event);
-		
+
 		if (drag_info.grab_frame < drag_info.last_pointer_frame) {
 			temporal_zoom_by_frame (drag_info.grab_frame, drag_info.last_pointer_frame, "mouse zoom");
 		} else {
 			temporal_zoom_by_frame (drag_info.last_pointer_frame, drag_info.grab_frame, "mouse zoom");
-		}		
+		}
 	} else {
 		temporal_zoom_to_frame (false, drag_info.grab_frame);
 		/*
@@ -5249,7 +5262,7 @@
  	if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()) && Config->get_rubberbanding_snaps_to_grid()) {
  		if (drag_info.first_move) {
  			snap_to (drag_info.grab_frame);
-		} 
+		}
 		snap_to (drag_info.current_pointer_frame);
  	}
 
@@ -5271,12 +5284,12 @@
 		y1 = drag_info.grab_y;
 	}
 
-	
+
 	if (start != end || y1 != y2) {
 
 		double x1 = frame_to_pixel (start);
 		double x2 = frame_to_pixel (end);
-		
+
 		rubberband_rect->property_x1() = x1;
 		rubberband_rect->property_y1() = y1;
 		rubberband_rect->property_x2() = x2;
@@ -5284,7 +5297,7 @@
 
 		rubberband_rect->show();
 		rubberband_rect->raise_to_top();
-		
+
 		drag_info.last_pointer_frame = drag_info.current_pointer_frame;
 		drag_info.first_move = false;
 
@@ -5319,12 +5332,12 @@
 			commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, track_views, op);
 		} else {
 			commit = select_all_within (drag_info.last_pointer_frame, drag_info.grab_frame, y1, y2, track_views, op);
-		}		
+		}
 
 		if (commit) {
 			commit_reversible_command ();
 		}
-		
+
 	} else {
 		selection->clear_tracks();
 		selection->clear_regions();
@@ -5408,16 +5421,16 @@
 		/* backwards drag of the left edge - not usable */
 		return;
 	}
-	
+
 	nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region()->position();
 
 	float percentage = (double) newlen / (double) clicked_regionview->region()->length();
 
 #ifndef USE_RUBBERBAND
-	// Soundtouch uses percentage / 100 instead of normal (/ 1) 
+	// Soundtouch uses percentage / 100 instead of normal (/ 1)
 	if (clicked_regionview->region()->data_type() == DataType::AUDIO) {
 		percentage = (float) ((double) newlen - (double) clicked_regionview->region()->length()) / ((double) newlen) * 100.0f;
-#endif	
+#endif
 	}
 
 	begin_reversible_command (_("timestretch"));
@@ -5457,7 +5470,7 @@
 	}
 
 	/* don't brush a copy over the original */
-	
+
 	if (pos == rv->region()->position()) {
 		return;
 	}
@@ -5470,14 +5483,14 @@
 
 	boost::shared_ptr<Playlist> playlist = rtv->playlist();
 	double speed = rtv->get_diskstream()->speed();
-	
+
 	XMLNode &before = playlist->get_state();
 	playlist->add_region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (arv->audio_region())), (nframes_t) (pos * speed));
 	XMLNode &after = playlist->get_state();
 	session->add_command(new MementoCommand<Playlist>(*playlist.get(), &before, &after));
-	
+
 	// playlist is frozen, so we have to update manually
-	
+
 	playlist->Modified(); /* EMIT SIGNAL */
 }
 
@@ -5486,10 +5499,10 @@
 {
 	struct timeval now;
 	struct timeval delta;
-	
+
 	gettimeofday (&now, 0);
 	timersub (&now, &last_track_height_step_timestamp, &delta);
-	
+
 	if (delta.tv_sec * 1000000 + delta.tv_usec > 250000) { /* milliseconds */
 		current_stepping_trackview = 0;
 		return false;
Index: gtk2_ardour/midi_region_view.h
===================================================================
--- gtk2_ardour/midi_region_view.h	(Revision 3147)
+++ gtk2_ardour/midi_region_view.h	(Arbeitskopie)
@@ -129,11 +129,37 @@
 	void   delete_selection();
 	size_t selection_size() { return _selection.size(); }
 
-	void move_selection(double dx, double dy);
-	void note_dropped(ArdourCanvas::CanvasMidiEvent* ev, double dt, uint8_t dnote);
+	void   move_selection(double dx, double dy);
+	void   note_dropped(ArdourCanvas::CanvasMidiEvent* ev, double dt, uint8_t dnote);
 
-	void  begin_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end);
-	void update_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end, double dx, bool relative);
+	/**
+	 * This function is needed to subtract the region start in pixels
+	 * from world coordinates submitted by the mouse
+	 */
+	double get_position_pixels(void);
+
+	/**
+	 * This function is called by CanvasMidiNote when resizing starts,
+	 * i.e. when the user presses mouse-2 on the note
+	 * @param note_end which end of the note, NOTE_ON or NOTE_OFF
+	 */
+	void begin_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end);
+
+	/**
+	 * This function is called while the user moves the mouse when resizing notes
+	 * @param note_end which end of the note, NOTE_ON or NOTE_OFF
+	 * @param x the difference in mouse motion, ie the motion difference if relative=true
+	 *           or the absolute mouse position (track-relative) if relative is false
+	 * @param relative true if relative resizing is taking place, false if absolute resizing
+	 */
+	void update_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end, double x, bool relative);
+
+	/**
+	 * This function is called while the user releases the mouse button when resizing notes
+	 * @param note_end which end of the note, NOTE_ON or NOTE_OFF
+	 * @param event_x the absolute mouse position (track-relative)
+	 * @param relative true if relative resizing is taking place, false if absolute resizing
+	 */
 	void commit_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end, double event_x, bool relative);
 
 	enum MouseState { None, Pressed, SelectTouchDragging, SelectRectDragging, AddDragging, EraseTouchDragging };
@@ -147,11 +173,11 @@
 
   protected:
 
-    /* this constructor allows derived types
-       to specify their visibility requirements
-       to the TimeAxisViewItem parent class
-    */
-
+    /**
+     * this constructor allows derived types
+     * to specify their visibility requirements
+     * to the TimeAxisViewItem parent class
+     */
     MidiRegionView (ArdourCanvas::Group *,
 	                RouteTimeAxisView&,
 	                boost::shared_ptr<ARDOUR::MidiRegion>,
@@ -177,6 +203,11 @@
 	void clear_selection_except(ArdourCanvas::CanvasMidiEvent* ev);
 	void clear_selection() { clear_selection_except(NULL); }
 	void update_drag_selection(double last_x, double x, double last_y, double y);
+
+	/**
+	 * This function provides the snap function for pixel units (double)
+	 * instead of nframes_t
+	 */
 	double snap_to(double x);
 
 	double _default_note_length;
Index: gtk2_ardour/editor.cc
===================================================================
--- gtk2_ardour/editor.cc	(Revision 3147)
+++ gtk2_ardour/editor.cc	(Arbeitskopie)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000-2007 Paul Davis 
+    Copyright (C) 2000-2007 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -182,6 +182,7 @@
 Gdk::Cursor* Editor::speaker_cursor = 0;
 Gdk::Cursor* Editor::midi_pencil_cursor = 0;
 Gdk::Cursor* Editor::midi_select_cursor = 0;
+Gdk::Cursor* Editor::midi_resize_cursor = 0;
 Gdk::Cursor* Editor::midi_erase_cursor = 0;
 Gdk::Cursor* Editor::wait_cursor = 0;
 Gdk::Cursor* Editor::timebar_cursor = 0;
@@ -194,7 +195,7 @@
 }
 
 Editor::Editor ()
-	: 
+	:
 	  /* time display buttons */
 
 	  minsec_label (_("Mins:Secs")),
@@ -224,9 +225,9 @@
 
 	  edit_point_clock (X_("editpoint"), false, X_("EditPointClock"), true),
 	  zoom_range_clock (X_("zoomrange"), false, X_("ZoomRangeClock"), true, true),
-	  
+
 	  toolbar_selection_clock_table (2,3),
-	  
+
 	  automation_mode_button (_("mode")),
 	  global_automation_button (_("automation")),
 
@@ -266,7 +267,7 @@
 	drag_info.item = 0;
 	current_mixer_strip = 0;
 	current_bbt_points = 0;
-	
+
 	snap_type_strings =  I18N (_snap_type_strings);
 	snap_mode_strings =  I18N (_snap_mode_strings);
 	zoom_focus_strings = I18N (_zoom_focus_strings);
@@ -274,7 +275,7 @@
 #ifdef USE_RUBBERBAND
 	rb_opt_strings = I18N (_rb_opt_strings);
 #endif
-	
+
 	snap_threshold = 5.0;
 	bbt_beat_subdivision = 4;
 	canvas_width = 0;
@@ -370,7 +371,7 @@
 
 	frames_per_unit = 2048; /* too early to use reset_zoom () */
 	reset_hscrollbar_stepping ();
-	
+
 	zoom_focus = ZoomFocusLeft;
 	set_zoom_focus (ZoomFocusLeft);
  	zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
@@ -381,19 +382,19 @@
 	edit_controls_vbox.set_spacing (0);
 	horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled), false);
 	vertical_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling), true);
-	
+
 	track_canvas.set_hadjustment (horizontal_adjustment);
 	track_canvas.set_vadjustment (vertical_adjustment);
 	time_canvas.set_hadjustment (horizontal_adjustment);
 
 	track_canvas.signal_map_event().connect (mem_fun (*this, &Editor::track_canvas_map_handler));
 	time_canvas.signal_map_event().connect (mem_fun (*this, &Editor::time_canvas_map_handler));
-	
+
 	controls_layout.add (edit_controls_vbox);
 	controls_layout.set_name ("EditControlsBase");
 	controls_layout.add_events (Gdk::SCROLL_MASK);
 	controls_layout.signal_scroll_event().connect (mem_fun(*this, &Editor::control_layout_scroll), false);
-	
+
 	controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
 	controls_layout.signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
 	controls_layout.signal_size_request().connect (mem_fun (*this, &Editor::controls_layout_size_request));
@@ -412,7 +413,7 @@
 	setup_midi_toolbar ();
 
  	edit_point_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_point_clock_changed));
-	
+
 	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));
@@ -468,7 +469,7 @@
 	transport_mark_label.set_size_request (-1, (int)timebar_height);
 	transport_mark_label.set_alignment (1.0, 0.5);
 	transport_mark_label.set_padding (5,0);
-	
+
 	time_button_vbox.pack_start (minsec_label, false, false);
 	time_button_vbox.pack_start (smpte_label, false, false);
 	time_button_vbox.pack_start (frame_label, false, false);
@@ -480,7 +481,7 @@
 	time_button_event_box.add (time_button_vbox);
 	time_button_event_box.set_name ("TimebarLabelBase");
 	time_button_frame.set_shadow_type (Gtk::SHADOW_NONE);
-	
+
 	time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
 	time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
 
@@ -488,7 +489,7 @@
 	time_button_frame.set_name ("TimebarLabelBase");
 	time_button_frame.set_shadow_type (Gtk::SHADOW_ETCHED_OUT);
 
-	/* these enable us to have a dedicated window (for cursor setting, etc.) 
+	/* these enable us to have a dedicated window (for cursor setting, etc.)
 	   for the canvas areas.
 	*/
 
@@ -496,13 +497,13 @@
 
 	time_canvas_event_box.add (time_canvas_vbox);
 	time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
-	
+
 	edit_packer.set_col_spacings (0);
 	edit_packer.set_row_spacings (0);
 	edit_packer.set_homogeneous (false);
 	edit_packer.set_border_width (0);
 	edit_packer.set_name ("EditorWindow");
-	
+
 	edit_packer.attach (edit_vscrollbar,         3, 4, 1, 2,    FILL,        FILL|EXPAND, 0, 0);
 
 	edit_packer.attach (time_button_frame,       0, 2, 0, 1,    FILL,        SHRINK, 0, 0);
@@ -604,7 +605,7 @@
 
 	edit_group_add_button->signal_clicked().connect (mem_fun (*this, &Editor::new_edit_group));
 	edit_group_remove_button->signal_clicked().connect (mem_fun (*this, &Editor::remove_selected_edit_group));
-	
+
 	edit_group_display_button_box->pack_start (*edit_group_add_button);
 	edit_group_display_button_box->pack_start (*edit_group_remove_button);
 
@@ -627,23 +628,23 @@
 	region_name_cell->signal_edited().connect (mem_fun (*this, &Editor::region_name_edit));
 
 	region_list_display.get_selection()->set_select_function (mem_fun (*this, &Editor::region_list_selection_filter));
-	
+
 	TreeViewColumn* tv_col = region_list_display.get_column(0);
 	CellRendererText* renderer = dynamic_cast<CellRendererText*>(region_list_display.get_column_cell_renderer (0));
 	tv_col->add_attribute(renderer->property_text(), region_list_columns.name);
 	tv_col->add_attribute(renderer->property_foreground_gdk(), region_list_columns.color_);
-	
+
 	region_list_display.get_selection()->set_mode (SELECTION_MULTIPLE);
 	region_list_display.add_object_drag (region_list_columns.region.index(), "regions");
 
 	/* setup DnD handling */
-	
+
 	list<TargetEntry> region_list_target_table;
-	
+
 	region_list_target_table.push_back (TargetEntry ("text/plain"));
 	region_list_target_table.push_back (TargetEntry ("text/uri-list"));
 	region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
-	
+
 	region_list_display.add_drop_targets (region_list_target_table);
 	region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
 
@@ -656,7 +657,7 @@
 	region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
 	region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
 	// region_list_display.signal_popup_menu().connect (bind (mem_fun (*this, &Editor::show_region_list_display_context_menu), 1, 0));
-	
+
 	named_selection_scroller.add (named_selection_display);
 	named_selection_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
 
@@ -666,7 +667,7 @@
 	named_selection_display.set_headers_visible (false);
 	named_selection_display.set_size_request (100, -1);
 	named_selection_display.set_name ("NamedSelectionDisplay");
-	
+
 	named_selection_display.get_selection()->set_mode (SELECTION_SINGLE);
 	named_selection_display.set_size_request (100, -1);
 	named_selection_display.signal_button_release_event().connect (mem_fun(*this, &Editor::named_selection_display_button_release), false);
@@ -702,7 +703,7 @@
 	nlabel = manage (new Label (_("Edit Groups")));
 	nlabel->set_angle (-90);
 	the_notebook.append_page (*edit_group_display_packer, *nlabel);
-	
+
 	if (!Profile->get_sae()) {
 		nlabel = manage (new Label (_("Chunks")));
 		nlabel->set_angle (-90);
@@ -718,7 +719,7 @@
 	post_maximal_pane_position = 0;
 	edit_pane.pack1 (edit_packer, true, true);
 	edit_pane.pack2 (the_notebook, false, true);
-	
+
 	edit_pane.signal_size_allocate().connect (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
 
 	top_hbox.pack_start (toolbar_frame, false, true);
@@ -741,7 +742,7 @@
 	vpacker.pack_end (global_hpacker, true, true);
 
 	/* register actions now so that set_state() can find them and set toggles/checks etc */
-	
+
 	register_actions ();
 
 	snap_type = SnapToBeat;
@@ -828,7 +829,7 @@
 		{
 			image_socket_listener->close_connection() ;
 		}
-		
+
 		delete image_socket_listener ;
 		image_socket_listener = 0 ;
 	}
@@ -890,16 +891,16 @@
 Editor::show_window ()
 {
 	show_all_children ();
-	
+
 	/* re-hide editor list if necessary */
 	editor_list_button_toggled ();
 
 	/* now reset all audio_time_axis heights, because widgets might need
 	   to be re-hidden
 	*/
-	
+
 	TimeAxisView *tv;
-	
+
 	for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
 		tv = (static_cast<TimeAxisView*>(*i));
 		tv->reset_height ();
@@ -959,7 +960,7 @@
 		fpu = session->current_end_frame() / canvas_width;
 		zoom_range_clock.set ((nframes_t) floor (fpu * canvas_width));
 	}
-	
+
 	temporal_zoom (fpu);
 }
 
@@ -976,7 +977,7 @@
 
 	/*
 		_control_scroll_target is an optional<T>
-	
+
 		it acts like a pointer to an nframes_t, with
 		a operator conversion to boolean to check
 		that it has a value could possibly use
@@ -1002,7 +1003,7 @@
 
 	playhead_cursor->set_position (*_control_scroll_target);
 	UpdateAllTransportClocks (*_control_scroll_target);
-	
+
 	if (*_control_scroll_target > (current_page_frames() / 2)) {
 		/* try to center PH in window */
 		reset_x_origin (*_control_scroll_target - (current_page_frames()/2));
@@ -1045,7 +1046,7 @@
 void
 Editor::start_scrolling ()
 {
-	scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect 
+	scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
 		(mem_fun(*this, &Editor::update_current_screen));
 }
 
@@ -1066,7 +1067,7 @@
 
 	center_screen (frame);
 	playhead_cursor->set_position (frame);
-}	
+}
 
 void
 Editor::center_screen (nframes_t frame)
@@ -1075,7 +1076,7 @@
 
 	/* if we're off the page, then scroll.
 	 */
-	
+
 	if (frame < leftmost_frame || frame >= leftmost_frame + page) {
 		center_screen_internal (frame, page);
 	}
@@ -1085,7 +1086,7 @@
 Editor::center_screen_internal (nframes_t frame, float page)
 {
 	page /= 2;
-		
+
 	if (frame > page) {
 		frame -= (nframes_t) page;
 	} else {
@@ -1101,7 +1102,7 @@
 	ENSURE_GUI_THREAD (mem_fun (*this, &Editor::handle_new_duration));
 
 	nframes_t new_end = session->get_maximum_extent() + (nframes_t) floorf (current_page_frames() * 0.10f);
-				  
+
 	if (new_end > last_canvas_frame) {
 		last_canvas_frame = new_end;
 		horizontal_adjustment.set_upper (last_canvas_frame / frames_per_unit);
@@ -1115,7 +1116,7 @@
 Editor::update_title_s (const string & snap_name)
 {
 	ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
-	
+
 	update_title ();
 }
 
@@ -1218,7 +1219,7 @@
 		// force name
 		loc->set_name (_("Loop"));
 	}
-	
+
 	loc = session->locations()->auto_punch_location();
 	if (loc == 0) {
 		loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
@@ -1233,9 +1234,9 @@
 	}
 
 	Config->map_parameters (mem_fun (*this, &Editor::parameter_changed));
-	
+
 	session->StateSaved.connect (mem_fun(*this, &Editor::session_state_saved));
-	
+
 	refresh_location_display ();
 	session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
 	session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
@@ -1271,24 +1272,24 @@
 
 		TreeModel::Children rows = route_display_model->children();
 		TreeModel::Children::iterator i;
-	
+
 		no_route_list_redisplay = true;
-		
+
 		for (i = rows.begin(); i != rows.end(); ++i) {
 			TimeAxisView *tv =  (*i)[route_display_columns.tv];
 			RouteTimeAxisView *rtv;
-			
+
 			if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) != 0) {
 				if (rtv->route()->is_master()) {
 					route_list_display.get_selection()->unselect (i);
 				}
 			}
 		}
-		
+
 		no_route_list_redisplay = false;
 		redisplay_route_list ();
 	}
-	
+
 	switch (snap_type) {
 	case SnapToRegionStart:
 	case SnapToRegionEnd:
@@ -1311,7 +1312,7 @@
 Editor::build_cursors ()
 {
 	using namespace Gdk;
-	
+
 	Gdk::Color mbg ("#000000" ); /* Black */
 	Gdk::Color mfg ("#0000ff" ); /* Blue. */
 
@@ -1324,23 +1325,23 @@
 
 	Gdk::Color fbg ("#ffffff" );
 	Gdk::Color ffg  ("#000000" );
-	
+
 	{
 		RefPtr<Bitmap> source, mask;
-		
+
 		source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
 		mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
 		fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
 	}
-	
-	{ 
+
+	{
 		RefPtr<Bitmap> source, mask;
 		source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
 		mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
 		speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
 	}
-	
-	{ 
+
+	{
 		RefPtr<Bitmap> bits;
 		char pix[4] = { 0, 0, 0, 0 };
 		bits = Bitmap::create (pix, 2, 2);
@@ -1348,17 +1349,17 @@
 		transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
 	}
 
-	{ 
+	{
 		RefPtr<Bitmap> bits;
 		char pix[4] = { 0, 0, 0, 0 };
 		bits = Bitmap::create (pix, 2, 2);
 		Gdk::Color c;
 		transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
 	}
-	
 
+
 	grabber_cursor = new Gdk::Cursor (HAND2);
-	
+
 	{
 		Glib::RefPtr<Gdk::Pixbuf> grabber_edit_point_pixbuf (::get_icon ("grabber_edit_point"));
 		grabber_edit_point_cursor = new Gdk::Cursor (Gdk::Display::get_default(), grabber_edit_point_pixbuf, 5, 17);
@@ -1372,6 +1373,7 @@
 	timebar_cursor = new Gdk::Cursor(LEFT_PTR);
 	midi_pencil_cursor = new Gdk::Cursor (PENCIL);
 	midi_select_cursor = new Gdk::Cursor (CENTER_PTR);
+	midi_resize_cursor = new Gdk::Cursor (SIZING);
 	midi_erase_cursor = new Gdk::Cursor (DRAPED_BOX);
 }
 
@@ -1399,7 +1401,7 @@
 		} else {
 			items.push_back (MenuElem (_("Activate"), bind (mem_fun (*this, &Editor::set_fade_in_active), true)));
 		}
-		
+
 		items.push_back (SeparatorElem());
 
 		if (Profile->get_sae()) {
@@ -1422,9 +1424,9 @@
 		} else {
 			items.push_back (MenuElem (_("Activate"), bind (mem_fun (*this, &Editor::set_fade_out_active), true)));
 		}
-		
+
 		items.push_back (SeparatorElem());
-		
+
 		if (Profile->get_sae()) {
 			items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Linear)));
 			items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Slow)));
@@ -1493,7 +1495,7 @@
 
 	menu = (this->*build_menu_function)(frame);
 	menu->set_name ("ArdourContextMenu");
-	
+
 	/* now handle specific situations */
 
 	switch (item_type) {
@@ -1538,10 +1540,10 @@
 	if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
 
 		/* Bounce to disk */
-		
+
 		using namespace Menu_Helpers;
 		MenuList& edit_items  = menu->items();
-		
+
 		edit_items.push_back (SeparatorElem());
 
 		switch (clicked_routeview->audio_track()->freeze_state()) {
@@ -1552,7 +1554,7 @@
 		case AudioTrack::Frozen:
 			edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
 			break;
-			
+
 		case AudioTrack::UnFrozen:
 			edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
 			break;
@@ -1603,7 +1605,7 @@
 	if (rtv) {
 		boost::shared_ptr<Diskstream> ds;
 		boost::shared_ptr<Playlist> pl;
-		
+
 		if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) {
 			Playlist::RegionList* regions = pl->regions_at ((nframes_t) floor ( (double)frame * ds->speed()));
 			for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
@@ -1673,7 +1675,7 @@
 
 	analysis_window->set_regionmode();
 	analysis_window->analyze();
-	
+
 	analysis_window->present();
 }
 
@@ -1691,7 +1693,7 @@
 
 	analysis_window->set_rangemode();
 	analysis_window->analyze();
-	
+
 	analysis_window->present();
 }
 #endif /* FFT_ANALYSIS */
@@ -1724,7 +1726,7 @@
 
 	if (xfade->active()) {
 		str = _("Mute");
-	} else { 
+	} else {
 		str = _("Unmute");
 	}
 
@@ -1791,7 +1793,7 @@
 	Menu     *region_menu = manage (new Menu);
 	MenuList& items       = region_menu->items();
 	region_menu->set_name ("ArdourContextMenu");
-	
+
 	boost::shared_ptr<AudioRegion> ar;
 	boost::shared_ptr<MidiRegion>  mr;
 
@@ -1800,7 +1802,7 @@
 		mr = boost::dynamic_pointer_cast<MidiRegion> (region);
 	}
 
-	/* when this particular menu pops up, make the relevant region 
+	/* when this particular menu pops up, make the relevant region
 	   become selected.
 	*/
 
@@ -1857,7 +1859,7 @@
 		region_mute_item->set_active();
 		fooc.block (false);
 	}
-	
+
 	if (!Profile->get_sae()) {
 		items.push_back (CheckMenuElem (_("Opaque")));
 		CheckMenuItem* region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
@@ -1873,14 +1875,14 @@
 	if (region->at_natural_position()) {
 		items.back().set_sensitive (false);
 	}
-	
+
 	items.push_back (SeparatorElem());
-	
+
 	if (ar) {
-		
+
 		RegionView* rv = sv->find_view (ar);
 		AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
-		
+
 		if (!Profile->get_sae()) {
 			items.push_back (MenuElem (_("Reset Envelope"), mem_fun(*this, &Editor::reset_region_gain_envelopes)));
 
@@ -1892,11 +1894,11 @@
 				region_envelope_visible_item->set_active (true);
 				fooc.block (false);
 			}
-		
+
 			items.push_back (CheckMenuElem (_("Envelope Active")));
 			CheckMenuItem* region_envelope_active_item = static_cast<CheckMenuItem*> (&items.back());
 			fooc = region_envelope_active_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_active));
-			
+
 			if (ar->envelope_active()) {
 				fooc.block (true);
 				region_envelope_active_item->set_active (true);
@@ -1925,13 +1927,13 @@
 	items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_audio_region)));
 	items.push_back (MenuElem (_("Set Range Selection"), mem_fun (*this, &Editor::set_selection_from_region)));
 	items.push_back (SeparatorElem());
-			 
+
 	/* Nudge region */
 
 	Menu *nudge_menu = manage (new Menu());
 	MenuList& nudge_items = nudge_menu->items();
 	nudge_menu->set_name ("ArdourContextMenu");
-	
+
 	nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false, false))));
 	nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false, false))));
 	nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
@@ -1943,12 +1945,12 @@
 	Menu *trim_menu = manage (new Menu);
 	MenuList& trim_items = trim_menu->items();
 	trim_menu->set_name ("ArdourContextMenu");
-	
+
 	trim_items.push_back (MenuElem (_("Start to edit point"), mem_fun(*this, &Editor::trim_region_from_edit_point)));
 	trim_items.push_back (MenuElem (_("Edit point to end"), mem_fun(*this, &Editor::trim_region_to_edit_point)));
 	trim_items.push_back (MenuElem (_("Trim To Loop"), mem_fun(*this, &Editor::trim_region_to_loop)));
 	trim_items.push_back (MenuElem (_("Trim To Punch"), mem_fun(*this, &Editor::trim_region_to_punch)));
-			     
+
 	items.push_back (MenuElem (_("Trim"), *trim_menu));
 	items.push_back (SeparatorElem());
 
@@ -1979,7 +1981,7 @@
 		menu_item_name.replace (pos, 1, "__");
 		pos += 2;
 	}
-	
+
 	edit_items.push_back (MenuElem (menu_item_name, *region_menu));
 	edit_items.push_back (SeparatorElem());
 }
@@ -2002,7 +2004,7 @@
 	items.push_back (SeparatorElem());
 	items.push_back (MenuElem (_("Analyze range"), mem_fun(*this, &Editor::analyze_range_selection)));
 #endif
-	
+
 	items.push_back (SeparatorElem());
 	items.push_back (MenuElem (_("Extend Range to End of Region"), bind (mem_fun(*this, &Editor::extend_selection_to_end_of_region), false)));
 	items.push_back (MenuElem (_("Extend Range to Start of Region"), bind (mem_fun(*this, &Editor::extend_selection_to_start_of_region), false)));
@@ -2010,14 +2012,14 @@
 	items.push_back (SeparatorElem());
 	items.push_back (MenuElem (_("Convert to region in-place"), mem_fun(*this, &Editor::separate_region_from_selection)));
 	items.push_back (MenuElem (_("Convert to region in region list"), mem_fun(*this, &Editor::new_region_from_selection)));
-	
+
 	items.push_back (SeparatorElem());
 	items.push_back (MenuElem (_("Select all in range"), mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
 
 	items.push_back (SeparatorElem());
 	items.push_back (MenuElem (_("Set loop from selection"), bind (mem_fun(*this, &Editor::set_loop_from_selection), false)));
 	items.push_back (MenuElem (_("Set punch from selection"), mem_fun(*this, &Editor::set_punch_from_selection)));
-	
+
 	items.push_back (SeparatorElem());
 	items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_selection)));
 	items.push_back (SeparatorElem());
@@ -2030,7 +2032,7 @@
 	items.push_back (MenuElem (_("Export range"), mem_fun(*this, &Editor::export_selection)));
 }
 
-	
+
 void
 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
 {
@@ -2041,13 +2043,13 @@
 	Menu *play_menu = manage (new Menu);
 	MenuList& play_items = play_menu->items();
 	play_menu->set_name ("ArdourContextMenu");
-	
+
 	play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point)));
 	play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
 	play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
 	play_items.push_back (SeparatorElem());
 	play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
-	
+
 	edit_items.push_back (MenuElem (_("Play"), *play_menu));
 
 	/* Selection */
@@ -2055,7 +2057,7 @@
 	Menu *select_menu = manage (new Menu);
 	MenuList& select_items = select_menu->items();
 	select_menu->set_name ("ArdourContextMenu");
-	
+
 	select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
 	select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
 	select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
@@ -2081,7 +2083,7 @@
 	Menu *cutnpaste_menu = manage (new Menu);
 	MenuList& cutnpaste_items = cutnpaste_menu->items();
 	cutnpaste_menu->set_name ("ArdourContextMenu");
-	
+
 	cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
 	cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
 	cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
@@ -2098,7 +2100,7 @@
 	edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
 
 	/* Adding new material */
-	
+
 	edit_items.push_back (SeparatorElem());
 	edit_items.push_back (MenuElem (_("Insert Selected Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
 	edit_items.push_back (MenuElem (_("Insert Existing Media"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
@@ -2108,7 +2110,7 @@
 	Menu *nudge_menu = manage (new Menu());
 	MenuList& nudge_items = nudge_menu->items();
 	nudge_menu->set_name ("ArdourContextMenu");
-	
+
 	edit_items.push_back (SeparatorElem());
 	nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
 	nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
@@ -2128,7 +2130,7 @@
 	Menu *play_menu = manage (new Menu);
 	MenuList& play_items = play_menu->items();
 	play_menu->set_name ("ArdourContextMenu");
-	
+
 	play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point)));
 	play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
 	edit_items.push_back (MenuElem (_("Play"), *play_menu));
@@ -2138,7 +2140,7 @@
 	Menu *select_menu = manage (new Menu);
 	MenuList& select_items = select_menu->items();
 	select_menu->set_name ("ArdourContextMenu");
-	
+
 	select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
 	select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
 	select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
@@ -2156,7 +2158,7 @@
 	Menu *cutnpaste_menu = manage (new Menu);
 	MenuList& cutnpaste_items = cutnpaste_menu->items();
 	cutnpaste_menu->set_name ("ArdourContextMenu");
-	
+
 	cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
 	cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
 	cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
@@ -2164,7 +2166,7 @@
 	Menu *nudge_menu = manage (new Menu());
 	MenuList& nudge_items = nudge_menu->items();
 	nudge_menu->set_name ("ArdourContextMenu");
-	
+
 	edit_items.push_back (SeparatorElem());
 	nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
 	nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
@@ -2176,15 +2178,15 @@
 
 void
 Editor::set_snap_to (SnapType st)
-{	
+{
 	unsigned int snap_ind = (unsigned int)st;
 	snap_type = st;
-	
+
 	if (snap_ind > snap_type_strings.size() - 1) {
 		snap_ind = 0;
 		snap_type = (SnapType)snap_ind;
 	}
-	
+
 	string str = snap_type_strings[snap_ind];
 
 	if (str != snap_type_selector.get_active_text()) {
@@ -2313,7 +2315,7 @@
 		   position may be zero already, and it does nothing in such
 		   circumstances.
 		*/
-		
+
 		leftmost_frame = 0;
 		horizontal_adjustment.set_value (0);
 	}
@@ -2374,7 +2376,7 @@
 			tact->set_active (yn);
 		}
 	}
-	
+
 	if ((prop = node.property ("show-measures"))) {
 		bool yn = (prop->value() == "yes");
 		_show_measures = !yn;
@@ -2400,7 +2402,7 @@
 	}
 
 	if ((prop = node.property ("region-list-sort-type"))) {
-		region_list_sort_type = (Editing::RegionListSortType) -1; // force change 
+		region_list_sort_type = (Editing::RegionListSortType) -1; // force change
 		reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
 	}
 
@@ -2419,12 +2421,12 @@
 			bool yn = (prop->value() == X_("yes"));
 
 			/* do it twice to force the change */
-			
+
 			tact->set_active (!yn);
 			tact->set_active (yn);
 		}
 	}
-	
+
 	if ((prop = node.property ("show-editor-list"))) {
 
 		Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
@@ -2435,7 +2437,7 @@
 			bool yn = (prop->value() == X_("yes"));
 
 			/* do it twice to force the change */
-			
+
 			tact->set_active (!yn);
 			tact->set_active (yn);
 		}
@@ -2453,15 +2455,15 @@
 
 	_id.print (buf, sizeof (buf));
 	node->add_property ("id", buf);
-	
+
 	if (is_realized()) {
 		Glib::RefPtr<Gdk::Window> win = get_window();
-		
+
 		int x, y, xoff, yoff, width, height;
 		win->get_root_origin(x, y);
 		win->get_position(xoff, yoff);
 		win->get_size(width, height);
-		
+
 		XMLNode* geometry = new XMLNode ("geometry");
 
 		snprintf(buf, sizeof(buf), "%d", width);
@@ -2483,7 +2485,7 @@
 	}
 
 	maybe_add_mixer_strip_width (*node);
-	
+
 	snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
 	node->add_property ("zoom-focus", buf);
 	snprintf (buf, sizeof(buf), "%f", frames_per_unit);
@@ -2505,13 +2507,13 @@
 	node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
 	node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
 	node->add_property ("mouse-mode", enum2str(mouse_mode));
-	
+
 	Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
 	if (act) {
 		Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
 		node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
 	}
-	
+
 	act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
 	if (act) {
 		Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
@@ -2583,13 +2585,13 @@
 			start += session->smpte_offset ();
 		} else {
 			start -= session->smpte_offset ();
-		}    
+		}
 		if (((direction == 0) && (start % one_smpte_second > one_smpte_second / 2)) || direction > 0) {
 			start = (nframes_t) ceil ((double) start / one_smpte_second) * one_smpte_second;
 		} else {
 			start = (nframes_t) floor ((double) start / one_smpte_second) * one_smpte_second;
 		}
-		
+
 		if (session->smpte_offset_negative())
 		{
 			start -= session->smpte_offset ();
@@ -2597,7 +2599,7 @@
 			start += session->smpte_offset ();
 		}
 		break;
-		
+
 	case SnapToSMPTEMinutes:
 		if (session->smpte_offset_negative())
 		{
@@ -2617,7 +2619,7 @@
 			start += session->smpte_offset ();
 		}
 		break;
-		
+
 	case SnapToSeconds:
 		if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
 			start = (nframes_t) ceil ((double) start / one_second) * one_second;
@@ -2625,7 +2627,7 @@
 			start = (nframes_t) floor ((double) start / one_second) * one_second;
 		}
 		break;
-		
+
 	case SnapToMinutes:
 		if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
 			start = (nframes_t) ceil ((double) start / one_minute) * one_minute;
@@ -2714,7 +2716,7 @@
 			} else {
 				i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
 			}
-			
+
 			if (i != region_boundary_cache.end()) {
 
 				/* lower bound doesn't quite to the right thing for our purposes */
@@ -2728,31 +2730,31 @@
 			} else {
 				start = region_boundary_cache.back();
 			}
-		} 
+		}
 		break;
 	}
 
 	switch (snap_mode) {
 	case SnapNormal:
-		return;			
-		
+		return;
+
 	case SnapMagnetic:
-		
+
 		if (presnap > start) {
 			if (presnap > (start + unit_to_frame(snap_threshold))) {
 				start = presnap;
 			}
-			
+
 		} else if (presnap < start) {
 			if (presnap < (start - unit_to_frame(snap_threshold))) {
 				start = presnap;
 			}
 		}
-		
+
 	default:
 		/* handled at entry */
 		return;
-		
+
 	}
 }
 
@@ -2837,7 +2839,7 @@
 	mouse_note_button.set_relief(Gtk::RELIEF_NONE);
 	mouse_mode_buttons.push_back (&mouse_note_button);
 	mouse_mode_buttons.push_back (&mouse_audition_button);
-	
+
 	mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
 
 	HBox* mode_box = manage(new HBox);
@@ -2869,17 +2871,17 @@
 
 	mode_box->pack_start(edit_mode_selector);
 	mode_box->pack_start(mouse_mode_button_box);
-	
+
 	mouse_mode_tearoff = manage (new TearOff (*mode_box));
 	mouse_mode_tearoff->set_name ("MouseModeBase");
 
-	mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
+	mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
 						  &mouse_mode_tearoff->tearoff_window()));
-	mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
+	mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
 						  &mouse_mode_tearoff->tearoff_window(), 1));
-	mouse_mode_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
+	mouse_mode_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
 						  &mouse_mode_tearoff->tearoff_window()));
-	mouse_mode_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
+	mouse_mode_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
 						   &mouse_mode_tearoff->tearoff_window(), 1));
 
 	mouse_move_button.set_name ("MouseModeButton");
@@ -2917,10 +2919,10 @@
 	mouse_note_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseNote));
 
 	// mouse_move_button.set_active (true);
-	
 
+
 	/* Zoom */
-	
+
 	zoom_box.set_spacing (1);
 	zoom_box.set_border_width (0);
 
@@ -2929,7 +2931,7 @@
 	zoom_in_button.add (*(manage (new Image (::get_icon("zoom_in")))));
 	zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
 	ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom In"));
-	
+
 	zoom_out_button.set_name ("EditorTimeButton");
 	zoom_out_button.set_size_request(-1,16);
 	zoom_out_button.add (*(manage (new Image (::get_icon("zoom_out")))));
@@ -3001,13 +3003,13 @@
 	tools_tearoff = manage (new TearOff (*hbox));
 	tools_tearoff->set_name ("MouseModeBase");
 
-	tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
+	tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
 					     &tools_tearoff->tearoff_window()));
-	tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
+	tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
 					     &tools_tearoff->tearoff_window(), 0));
-	tools_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
+	tools_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
 					     &tools_tearoff->tearoff_window()));
-	tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
+	tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
 					      &tools_tearoff->tearoff_window(), 0));
 
 	toolbar_hbox.set_spacing (10);
@@ -3016,13 +3018,13 @@
 	toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
 	toolbar_hbox.pack_start (*tools_tearoff, false, false);
 
-	
+
 	hbox->pack_start (snap_box, false, false);
-	// hbox->pack_start (zoom_box, false, false); 
+	// hbox->pack_start (zoom_box, false, false);
 	hbox->pack_start (*nudge_box, false, false);
 
 	hbox->show_all ();
-	
+
 	toolbar_base.set_name ("ToolBarBase");
 	toolbar_base.add (toolbar_hbox);
 
@@ -3047,54 +3049,62 @@
 	midi_tool_select_button.add (*(manage (new Image (::get_icon("midi_tool_select")))));
 	midi_tool_select_button.set_relief(Gtk::RELIEF_NONE);
 	midi_tool_buttons.push_back (&midi_tool_select_button);
+	midi_tool_resize_button.add (*(manage (new Image (::get_icon("strip_width")))));
+	midi_tool_resize_button.set_relief(Gtk::RELIEF_NONE);
+	midi_tool_buttons.push_back (&midi_tool_resize_button);
 	midi_tool_erase_button.add (*(manage (new Image (::get_icon("midi_tool_erase")))));
 	midi_tool_erase_button.set_relief(Gtk::RELIEF_NONE);
 	midi_tool_buttons.push_back (&midi_tool_erase_button);
 
 	midi_tool_pencil_button.set_active(true);
-	
+
 	midi_tool_button_set = new GroupedButtons (midi_tool_buttons);
 
 	midi_tool_button_box.set_border_width (2);
-	midi_tool_button_box.set_spacing(4);
 	midi_tool_button_box.set_spacing(1);
 	midi_tool_button_box.pack_start(midi_tool_pencil_button, true, true);
 	midi_tool_button_box.pack_start(midi_tool_select_button, true, true);
+	midi_tool_button_box.pack_start(midi_tool_resize_button, true, true);
 	midi_tool_button_box.pack_start(midi_tool_erase_button, true, true);
 	midi_tool_button_box.set_homogeneous(true);
 
 	midi_tool_pencil_button.set_name ("MouseModeButton");
 	midi_tool_select_button.set_name ("MouseModeButton");
-	midi_tool_erase_button.set_name ("MouseModeButton");
+	midi_tool_resize_button.set_name ("MouseModeButton");
+	midi_tool_erase_button.set_name  ("MouseModeButton");
 
 	ARDOUR_UI::instance()->tooltips().set_tip (midi_tool_pencil_button, _("Add/Move/Stretch Notes"));
 	ARDOUR_UI::instance()->tooltips().set_tip (midi_tool_select_button, _("Select/Move Notes"));
+	ARDOUR_UI::instance()->tooltips().set_tip (midi_tool_resize_button, _("Resize Notes"));
 	ARDOUR_UI::instance()->tooltips().set_tip (midi_tool_erase_button, _("Erase Notes"));
 
 	midi_tool_pencil_button.unset_flags (CAN_FOCUS);
 	midi_tool_select_button.unset_flags (CAN_FOCUS);
+	midi_tool_resize_button.unset_flags (CAN_FOCUS);
 	midi_tool_erase_button.unset_flags (CAN_FOCUS);
-	
+
 	midi_tool_pencil_button.signal_toggled().connect (bind (mem_fun(*this,
 				&Editor::midi_edit_mode_toggled), Editing::MidiEditPencil));
 	midi_tool_select_button.signal_toggled().connect (bind (mem_fun(*this,
 				&Editor::midi_edit_mode_toggled), Editing::MidiEditSelect));
+	midi_tool_resize_button.signal_toggled().connect (bind (mem_fun(*this,
+				&Editor::midi_edit_mode_toggled), Editing::MidiEditResize));
 	midi_tool_erase_button.signal_toggled().connect (bind (mem_fun(*this,
 				&Editor::midi_edit_mode_toggled), Editing::MidiEditErase));
-	
+
 	/* Pack everything in... */
 
 	midi_tools_tearoff = manage (new TearOff (midi_tool_button_box));
 	midi_tools_tearoff->set_name ("MouseModeBase");
 
 	/*
-	midi_tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&midi_toolbar_hbox), 
+	midi_tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&midi_toolbar_hbox),
 					     &midi_tools_tearoff->tearoff_window()));
-	midi_tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&midi_toolbar_hbox), 
+	midi_tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&midi_toolbar_hbox),
 					     &midi_tools_tearoff->tearoff_window(), 0));
-	midi_tools_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&midi_toolbar_hbox), 
+	midi_tools_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&midi_toolbar_hbox),
 					     &midi_tools_tearoff->tearoff_window()));
-	midi_tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&midi_toolbar_hbox), 
+	midi_tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&midi_toolbar_hbox),
 					      &midi_tools_tearoff->tearoff_window(), 0));
 	*/
 
@@ -3106,7 +3116,7 @@
 	midi_tool_button_box.show_all ();
 	midi_toolbar_hbox.show_all();
 	midi_tools_tearoff->show_all();
-	
+
 	midi_toolbar_base.set_name ("ToolBarBase");
 	midi_toolbar_base.add (midi_toolbar_hbox);
 
@@ -3116,15 +3126,15 @@
 }
 
 int
-Editor::convert_drop_to_paths (vector<ustring>& paths, 
+Editor::convert_drop_to_paths (vector<ustring>& paths,
 			       const RefPtr<Gdk::DragContext>& context,
 			       gint                x,
 			       gint                y,
 			       const SelectionData& data,
 			       guint               info,
-			       guint               time)			       
+			       guint               time)
 
-{	
+{
 	if (session == 0) {
 		return -1;
 	}
@@ -3140,11 +3150,11 @@
 		if (data.get_target() != "text/plain") {
 			return -1;
 		}
-  
-		/* Parse the "uri-list" format that Nautilus provides, 
+
+		/* Parse the "uri-list" format that Nautilus provides,
 		   where each pathname is delimited by \r\n
 		*/
-	
+
 		const char* p = data.get_text().c_str();
 		const char* q;
 
@@ -3154,17 +3164,17 @@
 			{
 				while (g_ascii_isspace (*p))
 					p++;
-				
+
 				q = p;
 				while (*q && (*q != '\n') && (*q != '\r'))
 					q++;
-				
+
 				if (q > p)
 				{
 					q--;
 					while (q > p && g_ascii_isspace (*q))
 						q--;
-					
+
 					if (q > p)
 					{
 						uris.push_back (ustring (p, q - p + 1));
@@ -3180,16 +3190,16 @@
 			return -1;
 		}
 	}
-	
+
 	for (vector<ustring>::iterator i = uris.begin(); i != uris.end(); ++i) {
 
 		if ((*i).substr (0,7) == "file://") {
-			
+
 			ustring p = *i;
                         PBD::url_decode (p);
 
 			// scan forward past three slashes
-			
+
 			ustring::size_type slashcnt = 0;
 			ustring::size_type n = 0;
 			ustring::iterator x = p.begin();
@@ -3270,7 +3280,7 @@
 
 	*selection = *state->selection;
 	time_selection_changed ();
-	region_selection_changed ();   
+	region_selection_changed ();
 
 	/* XXX other selection change handlers? */
 }
@@ -3315,7 +3325,7 @@
 		route.set_mute (yn, this);
 	}
 }
-		
+
 void
 Editor::history_changed ()
 {
@@ -3353,7 +3363,7 @@
 
 	RegionSelection rs;
 	get_regions_for_action (rs);
-	
+
 	if (mouse_mode != MouseRange) {
 
 		if (rs.empty()) {
@@ -3368,16 +3378,16 @@
 		Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
 		SpinButton spinner (adjustment, 0.0, 1);
 		HBox hbox;
-		
+
 		win.get_vbox()->set_spacing (12);
 		win.get_vbox()->pack_start (hbox);
 		hbox.set_border_width (6);
 		hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
-		
+
 		/* dialogs have ::add_action_widget() but that puts the spinner in the wrong
 		   place, visually. so do this by hand.
 		*/
-		
+
 		hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
 		spinner.signal_activate().connect (sigc::bind (mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
 		spinner.grab_focus();
@@ -3385,22 +3395,22 @@
 		hbox.show ();
 		label.show ();
 		spinner.show ();
-		
+
 		win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
 		win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
 		win.set_default_response (RESPONSE_ACCEPT);
-		
+
 		win.set_position (WIN_POS_MOUSE);
-		
+
 		spinner.grab_focus ();
-		
+
 		switch (win.run ()) {
 		case RESPONSE_ACCEPT:
 			break;
 		default:
 			return;
 		}
-		
+
 		times = adjustment.get_value();
 	}
 
@@ -3494,7 +3504,7 @@
 	}
 
 	Config->set_edit_mode (mode);
-}	
+}
 
 void
 Editor::snap_type_selection_done ()
@@ -3544,7 +3554,7 @@
 	if (ract) {
 		ract->set_active ();
 	}
-}	
+}
 
 void
 Editor::snap_mode_selection_done ()
@@ -3628,14 +3638,14 @@
 		focus_type = ZoomFocusEdit;
 	} else {
 		focus_type = ZoomFocusMouse;
-	} 
-	
+	}
+
 	RefPtr<RadioAction> ract = zoom_focus_action (focus_type);
 
 	if (ract) {
 		ract->set_active ();
 	}
-}	
+}
 
 gint
 Editor::edit_controls_button_release (GdkEventButton* ev)
@@ -3675,16 +3685,16 @@
 		}
 
 	} else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
-		
+
 		/* just the view for this track
 		 */
 
 		v->push_back (track);
 
 	} else {
-		
+
 		/* views for all tracks in the edit group */
-		
+
 		for (i  = track_views.begin(); i != track_views.end (); ++i) {
 
 			if (group == 0 || (*i)->edit_group() == group) {
@@ -3692,7 +3702,7 @@
 			}
 		}
 	}
-	
+
 	return v;
 }
 
@@ -3704,7 +3714,7 @@
 	if (str != zoom_focus_selector.get_active_text()) {
 		zoom_focus_selector.set_active_text (str);
 	}
-	
+
 	if (zoom_focus != f) {
 		zoom_focus = f;
 
@@ -3720,7 +3730,7 @@
 	win.set_transient_for (*this);
 }
 
-void 
+void
 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
 {
 	/* recover or initialize pane positions. do this here rather than earlier because
@@ -3756,7 +3766,7 @@
 		} else {
 			pos = atoi (prop->value());
 		}
-		
+
 		if ((done = GTK_WIDGET(edit_pane.gobj())->allocation.width > pos)) {
 			edit_pane.set_position (pos);
 			pre_maximal_pane_position = pos;
@@ -3767,7 +3777,7 @@
 void
 Editor::detach_tearoff (Box* b, Window* w)
 {
-	if (tools_tearoff->torn_off() && 
+	if (tools_tearoff->torn_off() &&
 	    mouse_mode_tearoff->torn_off()) {
 		top_hbox.remove (toolbar_frame);
 	}
@@ -3844,16 +3854,16 @@
 	}
 
 	CrossfadeEditor cew (*session, xfade, xfade->fade_in().get_min_y(), 1.0);
-		
+
 	ensure_float (cew);
-	
+
 	switch (cew.run ()) {
 	case RESPONSE_ACCEPT:
 		break;
 	default:
 		return;
 	}
-	
+
 	cew.apply ();
 	xfade->StateChanged (Change (~0));
 }
@@ -3890,7 +3900,7 @@
 					"If left alone, no audio files used by it will be cleaned.\n"
 					"If deleted, audio files used by it alone by will cleaned."),
 				      pl->name()));
-	
+
 	dialog.set_position (WIN_POS_CENTER);
 	dialog.get_vbox()->pack_start (label);
 
@@ -3972,7 +3982,7 @@
 	case GDK_SCROLL_DOWN:
 		scroll_tracks_down_line ();
 		return true;
-		
+
 	default:
 		/* no left/right handling yet */
 		break;
@@ -3990,17 +4000,17 @@
 	if (snapshot_display.get_selection()->count_selected_rows() > 0) {
 
 		TreeModel::iterator i = snapshot_display.get_selection()->get_selected();
-		
+
 		Glib::ustring snap_name = (*i)[snapshot_display_columns.real_name];
 
 		if (snap_name.length() == 0) {
 			return;
 		}
-		
+
 		if (session->snap_name() == snap_name) {
 			return;
 		}
-		
+
 		ARDOUR_UI::instance()->load_session(session->path(), string (snap_name));
 	}
 }
@@ -4062,7 +4072,7 @@
 	prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
 	prompter.set_prompt (_("New name of snapshot"));
 	prompter.set_initial_text (old_name);
-	
+
 	if (prompter.run() == RESPONSE_ACCEPT) {
 		prompter.get_result (new_name);
 		if (new_name.length()) {
@@ -4114,18 +4124,18 @@
 	{
 		string statename = (*i);
 		TreeModel::Row row = *(snapshot_display_model->append());
-		
+
 		/* this lingers on in case we ever want to change the visible
 		   name of the snapshot.
 		*/
-		
+
 		string display_name;
 		display_name = statename;
 
 		if (statename == session->snap_name()) {
 			snapshot_display.get_selection()->select(row);
-		} 
-		
+		}
+
 		row[snapshot_display_columns.visible_name] = display_name;
 		row[snapshot_display_columns.real_name] = statename;
 	}
@@ -4156,7 +4166,7 @@
 
 	fullscreen();
 	if(post_maximal_editor_width) {
-		edit_pane.set_position (post_maximal_pane_position - 
+		edit_pane.set_position (post_maximal_pane_position -
 			abs(post_maximal_editor_width - pre_maximal_editor_width));
 	} else {
 		edit_pane.set_position (post_maximal_pane_position);
@@ -4191,7 +4201,7 @@
  *  @param v Track.
  */
 
-void 
+void
 Editor::new_playlists (TimeAxisView* v)
 {
 	begin_reversible_command (_("new playlists"));
@@ -4219,7 +4229,7 @@
  *  @param v Track.
  */
 
-void 
+void
 Editor::clear_playlists (TimeAxisView* v)
 {
 	begin_reversible_command (_("clear playlists"));
@@ -4227,7 +4237,7 @@
 	commit_reversible_command ();
 }
 
-void 
+void
 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz)
 {
 	atv.use_new_playlist (sz > 1 ? false : true);
@@ -4239,7 +4249,7 @@
 	atv.use_copy_playlist (sz > 1 ? false : true);
 }
 
-void 
+void
 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t sz)
 {
 	atv.clear_playlist ();
@@ -4285,7 +4295,7 @@
 		return;
 	}
 
-	/* note: the correct functionality here is very dependent on the ordering of 
+	/* note: the correct functionality here is very dependent on the ordering of
 	   setting zoom focus, horizontal position and finally zoom. this is because
 	   it is set_frames_per_unit() that overwrites last_visual_state.
 	*/
@@ -4310,7 +4320,7 @@
 		fpu = 2.0;
 	}
 
-	
+
 	/* don't allow zooms that fit more than the maximum number
 	   of frames into an 800 pixel wide space.
 	*/
@@ -4322,7 +4332,7 @@
 	if (fpu == frames_per_unit) {
 		return;
 	}
-	
+
 	last_visual_state.frames_per_unit = frames_per_unit;
 	last_visual_state.leftmost_frame = leftmost_frame;
 	last_visual_state.zoom_focus = zoom_focus;
@@ -4369,7 +4379,7 @@
 {
 	pending_visual_change.pending = VisualChange::Type (pending_visual_change.pending | VisualChange::TimeOrigin);
 	pending_visual_change.time_origin = where;
-	
+
 	if (pending_visual_change.idle_handler_id < 0) {
 		pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this);
 	}
@@ -4384,7 +4394,7 @@
 	if (pending_visual_change.idle_handler_id < 0) {
 		pending_visual_change.idle_handler_id = g_idle_add ( _idle_visual_changer, this);
 	}
-	
+
 }
 
 int
@@ -4409,7 +4419,7 @@
 		update_tempo_based_rulers ();
 	}
 	if (p & VisualChange::TimeOrigin) {
-		
+
 		nframes_t time_origin = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
 
 		if (time_origin != pending_visual_change.time_origin) {
@@ -4429,7 +4439,7 @@
 	    return a->order < b->order;
     }
 };
-	
+
 void
 Editor::sort_track_selection (TrackSelection* sel)
 {
@@ -4461,7 +4471,7 @@
 	case EditAtPlayhead:
 		where = session->audible_frame();
 		break;
-		
+
 	case EditAtSelectedMarker:
 		if (!selection->markers.empty()) {
 			bool is_start;
@@ -4474,9 +4484,9 @@
 				}
 				break;
 			}
-		} 
+		}
 		/* fallthru */
-		
+
 	default:
 	case EditAtMouse:
 		if (!mouse_frame (where, ignored)) {
@@ -4496,7 +4506,7 @@
 	if (!session) return;
 
 	begin_reversible_command (cmd);
-	
+
 	Location* tll;
 
 	if ((tll = transport_loop_location()) == 0) {
@@ -4514,7 +4524,7 @@
                 XMLNode &after = tll->get_state();
                 session->add_command (new MementoCommand<Location>(*tll, &before, &after));
 	}
-	
+
 	commit_reversible_command ();
 }
 
@@ -4524,7 +4534,7 @@
 	if (!session) return;
 
 	begin_reversible_command (cmd);
-	
+
 	Location* tpl;
 
 	if ((tpl = transport_punch_location()) == 0) {
@@ -4542,7 +4552,7 @@
                 XMLNode &after = tpl->get_state();
                 session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
 	}
-	
+
 	commit_reversible_command ();
 }
 
@@ -4558,13 +4568,13 @@
 	}
 
 	for (TrackSelection::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
-	
+
 		AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*t);
 
 		if (atv) {
 			boost::shared_ptr<Diskstream> ds;
 			boost::shared_ptr<Playlist> pl;
-			
+
 			if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
 
 				Playlist::RegionList* regions = pl->regions_at ((nframes_t) floor ( (double)where * ds->speed()));
@@ -4596,13 +4606,13 @@
 	}
 
 	for (TrackSelection::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
-	
+
 		AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*t);
 
 		if (atv) {
 			boost::shared_ptr<Diskstream> ds;
 			boost::shared_ptr<Playlist> pl;
-			
+
 			if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
 
 				Playlist::RegionList* regions = pl->regions_touched ((nframes_t) floor ( (double)where * ds->speed()), max_frames);
@@ -4632,7 +4642,7 @@
 			/* no regions or tracks selected, but entered regionview is valid
 			   and we're in object mode - just use entered regionview
 			*/
-			
+
 			if (entered_regionview && (mouse_mode == Editing::MouseObject)) {
 				rs.add (entered_regionview);
 				return;
@@ -4641,7 +4651,7 @@
 		} else {
 
 			/* no regions selected, so get all regions at the edit point across
-			   all selected tracks. 
+			   all selected tracks.
 			*/
 
 			nframes64_t where = get_preferred_edit_position();
@@ -4652,14 +4662,14 @@
 			*/
 
 			if (entered_regionview != 0 &&
-			    !selection->selected (entered_regionview) && 
+			    !selection->selected (entered_regionview) &&
 			    !selection->selected (&entered_regionview->get_time_axis_view())) {
 				rs.add (entered_regionview);
 			}
 		}
 
 	} else {
-		
+
 		/* just use the selected regions */
 
 		rs = selection->regions;
@@ -4680,34 +4690,34 @@
 {
 
 	for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
-		
+
 		RouteTimeAxisView* tatv;
-		
+
 		if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
-			
+
 			boost::shared_ptr<Playlist> pl;
 			vector<boost::shared_ptr<Region> > results;
 			RegionView* marv;
 			boost::shared_ptr<Diskstream> ds;
-			
+
 			if ((ds = tatv->get_diskstream()) == 0) {
 				/* bus */
 				continue;
 			}
-			
+
 			if ((pl = (ds->playlist())) != 0) {
 				pl->get_region_list_equivalent_regions (region, results);
 			}
-			
+
 			for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
 				if ((marv = tatv->view()->find_view (*ir)) != 0) {
 					regions.push_back (marv);
 				}
 			}
-			
+
 		}
 	}
-}	
+}
 
 void
 Editor::show_rhythm_ferret ()
Index: gtk2_ardour/canvas-note.cc
===================================================================
--- gtk2_ardour/canvas-note.cc	(Revision 3147)
+++ gtk2_ardour/canvas-note.cc	(Arbeitskopie)
@@ -12,38 +12,39 @@
 CanvasNote::on_event(GdkEvent* ev)
 {
 	double          event_x;
-	static double   middle_point, pressed_x, last_x;
+	static double   middle_point, last_x;
 	Gdk::Cursor     cursor;
 	static NoteEnd  note_end;
+	Editing::MidiEditMode edit_mode = _region.get_trackview().editor.current_midi_edit_mode();
 
 	switch(ev->type) {
 	case GDK_BUTTON_PRESS:
-		if (ev->button.button == 2) {
+		if (ev->button.button == 2 ||
+				(ev->button.button == 1 &&
+				 edit_mode == Editing::MidiEditResize)) {
+			double region_start = _region.get_position_pixels();
 			event_x = ev->button.x;
-			middle_point = x1() + (x2() - x1()) / 2.0L;
+			middle_point = region_start + x1() + (x2() - x1()) / 2.0L;
 
 			if(event_x <= middle_point) {
 				cursor = Gdk::Cursor(Gdk::LEFT_SIDE);
-				last_x = x1();
 				note_end = NOTE_ON;
 			} else {
 				cursor = Gdk::Cursor(Gdk::RIGHT_SIDE);
-				last_x = x2();
 				note_end = NOTE_OFF;
 			}
 
 			_item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, cursor, ev->motion.time);
 
 			if (_region.mouse_state() == MidiRegionView::SelectTouchDragging) {
-				_mouse2_state = AbsoluteResize;
+				_note_state = AbsoluteResize;
 			} else {
-				_mouse2_state = RelativeResize;
+				_note_state = RelativeResize;
 			}
 
-			pressed_x = event_x;
-
 			_region.note_selected(this, true);
 			_region.begin_resizing(note_end);
+			last_x = event_x;
 
 			return true;
 		}
@@ -51,13 +52,13 @@
 	case GDK_MOTION_NOTIFY:
 		event_x = ev->motion.x;
 
-		if (_mouse2_state == RelativeResize) {
+		if (_note_state == RelativeResize) {
 			_region.update_resizing(note_end, event_x - last_x, true);
 			last_x = event_x;
 			return true;
 		}
 
-		if (_mouse2_state == AbsoluteResize) {
+		if (_note_state == AbsoluteResize) {
 			_region.update_resizing(note_end, event_x, false);
 			return true;
 		}
@@ -65,17 +66,17 @@
 	case GDK_BUTTON_RELEASE:
 		event_x = ev->button.x;
 
-		switch (_mouse2_state) {
+		switch (_note_state) {
 		case RelativeResize: // Clicked
 			_item->ungrab(ev->button.time);
 			_region.commit_resizing(note_end, event_x, true);
-			_mouse2_state = None;
+			_note_state = None;
 			return true;
 
 		case AbsoluteResize: // Clicked
 			_item->ungrab(ev->button.time);
 			_region.commit_resizing(note_end, event_x, false);
-			_mouse2_state = None;
+			_note_state = None;
 			return true;
 
 		default:
Index: gtk2_ardour/midi_region_view.cc
===================================================================
--- gtk2_ardour/midi_region_view.cc	(Revision 3147)
+++ gtk2_ardour/midi_region_view.cc	(Arbeitskopie)
@@ -840,6 +840,24 @@
 	}
 }
 
+
+double
+MidiRegionView::snap_to(double x)
+{
+	PublicEditor &editor = trackview.editor;
+
+	nframes_t frame = editor.pixel_to_frame(x);
+	editor.snap_to(frame);
+	return (double) editor.frame_to_pixel(frame);
+}
+
+double
+MidiRegionView::get_position_pixels(void)
+{
+	nframes_t  region_frame  = get_position();
+	return trackview.editor.frame_to_pixel(region_frame);
+}
+
 void
 MidiRegionView::begin_resizing(CanvasNote::NoteEnd note_end)
 {
@@ -853,18 +871,34 @@
 			NoteResizeData *resize_data = new NoteResizeData();
 			resize_data->canvas_note = note;
 
-			SimpleRect *resize_rect = new SimpleRect(*group, note->x1(), note->y1(), note->x2(), note->y2());
+			// create a new SimpleRect from the note which will be the resize preview
+			SimpleRect *resize_rect =
+				new SimpleRect(
+						*group,
+						note->x1(),
+						note->y1(),
+						note->x2(),
+						note->y2());
 
-			uint fill_color = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->canvasvar_MidiNoteSelectedOutline.get(), 128);
+			// calculate the colors: get the color settings
+			uint fill_color =
+				UINT_RGBA_CHANGE_A(
+						ARDOUR_UI::config()->canvasvar_MidiNoteSelectedOutline.get(),
+						128);
+
+			// make the resize preview notes more transparent and bright
 			fill_color = UINT_INTERPOLATE(fill_color, 0xFFFFFF40, 0.5);
 
+			// calculate color based on note velocity
 			resize_rect->property_fill_color_rgba() =
 				UINT_INTERPOLATE(
 					note_fill_color(note->note()->velocity()),
 					fill_color,
 					0.85);
 
-			resize_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiNoteSelectedOutline.get();
+			resize_rect->property_outline_color_rgba() =
+				ARDOUR_UI::config()->canvasvar_MidiNoteSelectedOutline.get();
+
 			resize_data->resize_rect = resize_rect;
 
 			if(note_end == CanvasNote::NOTE_ON) {
@@ -878,38 +912,33 @@
 	}
 }
 
-double
-MidiRegionView::snap_to(double x)
-{
-	PublicEditor &editor = trackview.editor;
-
-	nframes_t frame = editor.pixel_to_frame(x);
-	editor.snap_to(frame);
-	return (double) editor.frame_to_pixel(frame);
-}
-
 void
-MidiRegionView::update_resizing(CanvasNote::NoteEnd note_end, double dx, bool relative)
+MidiRegionView::update_resizing(CanvasNote::NoteEnd note_end, double x, bool relative)
 {
-
-
 	for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
 		SimpleRect     *resize_rect = (*i)->resize_rect;
 		CanvasNote     *canvas_note = (*i)->canvas_note;
 
+		const double region_start = get_position_pixels();
+
 		if(relative) {
-			(*i)->current_x = (*i)->current_x + dx;
+			(*i)->current_x = (*i)->current_x + x;
 		} else {
-			(*i)->current_x = dx;
+			// x is in track relative, transform it to region relative
+			(*i)->current_x = x - region_start;
 		}
 
 		double current_x = (*i)->current_x;
 
 		if(note_end == CanvasNote::NOTE_ON) {
-			resize_rect->property_x1() = snap_to(current_x);
+			// because snapping works on world coordinates we have to transform current_x
+			// to world coordinates before snapping and transform it back afterwards
+			resize_rect->property_x1() = snap_to(region_start + current_x) - region_start;
 			resize_rect->property_x2() = canvas_note->x2();
 		} else {
-			resize_rect->property_x2() = snap_to(current_x);
+			// because snapping works on world coordinates we have to transform current_x
+			// to world coordinates before snapping and transform it back afterwards
+			resize_rect->property_x2() = snap_to(region_start + current_x) - region_start;
 			resize_rect->property_x1() = canvas_note->x1();
 		}
 	}
@@ -921,17 +950,21 @@
 	start_delta_command();
 
 	for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
-		CanvasNote *canvas_note = (*i)->canvas_note;
-		SimpleRect *resize_rect = (*i)->resize_rect;
-		double      current_x   = (*i)->current_x;
+		CanvasNote  *canvas_note  = (*i)->canvas_note;
+		SimpleRect  *resize_rect  = (*i)->resize_rect;
+		double       current_x    = (*i)->current_x;
+		const double region_start = get_position_pixels();
 
-
 		if(!relative) {
-			current_x = event_x;
+			// event_x is in track relative, transform it to region relative
+			current_x = event_x - region_start;
 		}
 
-		nframes_t current_frame = trackview.editor.pixel_to_frame(current_x);
+		// because snapping works on world coordinates we have to transform current_x
+		// to world coordinates before snapping and transform it back afterwards
+		nframes_t current_frame = trackview.editor.pixel_to_frame(current_x + region_start);
 		trackview.editor.snap_to(current_frame);
+		current_frame -= get_position();
 
 		const boost::shared_ptr<Note> copy(new Note(*(canvas_note->note().get())));
 
Index: gtk2_ardour/editor.h
===================================================================
--- gtk2_ardour/editor.h	(Revision 3147)
+++ gtk2_ardour/editor.h	(Arbeitskopie)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000-2003 Paul Davis 
+    Copyright (C) 2000-2003 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -153,7 +153,7 @@
 	void set_mouse_mode (Editing::MouseMode, bool force=true);
 	void step_mouse_mode (bool next);
 	Editing::MouseMode current_mouse_mode () const { return mouse_mode; }
-	
+
 	void set_midi_edit_cursor (Editing::MidiEditMode);
 	void set_midi_edit_mode (Editing::MidiEditMode, bool force=true);
 	Editing::MidiEditMode current_midi_edit_mode () const { return midi_edit_mode; }
@@ -183,7 +183,7 @@
 
 	void set_show_waveforms_recording (bool yn);
 	bool show_waveforms_recording() const { return _show_waveforms_recording; }
-	
+
 	/* things that need to be public to be used in the main menubar */
 
 	void new_region_from_selection ();
@@ -200,7 +200,7 @@
 	nframes_t unit_to_frame (double unit) const {
 		return (nframes_t) rint (unit * frames_per_unit);
 	}
-	
+
 	double frame_to_unit (nframes_t frame) const {
 		return rint ((double) frame / (double) frames_per_unit);
 	}
@@ -213,11 +213,11 @@
 	   the result of using the world->canvas affine transform on a
 	   world coordinate. These coordinates already take into
 	   account any scrolling carried out by adjusting the
-	   xscroll_adjustment.  
+	   xscroll_adjustment.
 	*/
 
 	nframes64_t pixel_to_frame (double pixel) const {
-		
+
 		/* pixel can be less than zero when motion events
 		   are processed. since we've already run the world->canvas
 		   affine, that means that the location *really* is "off
@@ -266,7 +266,7 @@
 	/* export */
 
 	/* these initiate export ... */
-	
+
 	void export_session();
 	void export_selection();
 
@@ -311,7 +311,7 @@
 	void nudge_backward_capture_offset ();
 
 	/* playhead/screen stuff */
-	
+
 	void set_follow_playhead (bool yn);
 	void toggle_follow_playhead ();
 	bool follow_playhead() const { return _follow_playhead; }
@@ -345,7 +345,7 @@
 	/* layers */
 	void set_layer_model (ARDOUR::LayerModel);
 	void update_layering_model ();
-	
+
 	void toggle_link_region_and_track_selection ();
 
 	/* redirect shared ops menu. caller must free returned menu */
@@ -395,7 +395,7 @@
 
 	// to keep track of the playhead position for control_scroll
 	boost::optional<nframes_t> _control_scroll_target;
- 
+
 	PlaylistSelector* _playlist_selector;
 
 	struct VisualState {
@@ -403,7 +403,7 @@
 	    nframes_t leftmost_frame;
 	    Editing::ZoomFocus zoom_focus;
 	};
-	
+
 	VisualState last_visual_state;
 
 	nframes_t   leftmost_frame;
@@ -456,7 +456,7 @@
 	    bool    valid;
 
 	    LocationMarkers () : start(0), end(0), valid (true) {}
-	    
+
 	    ~LocationMarkers ();
 
 	    void hide();
@@ -523,7 +523,7 @@
 	bool set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, boost::weak_ptr<ARDOUR::Region>);
 	void collect_new_region_view (RegionView *);
 	void collect_and_select_new_region_view (RegionView *);
-	
+
 	Gtk::Menu track_context_menu;
 	Gtk::Menu track_region_context_menu;
 	Gtk::Menu track_selection_context_menu;
@@ -569,7 +569,7 @@
 	bool                 verbose_cursor_visible;
 
 	void parameter_changed (const char *);
-	
+
 	bool track_canvas_motion (GdkEvent*);
 
 	void set_verbose_canvas_cursor (const string &, double x, double y);
@@ -595,7 +595,7 @@
 	ArdourCanvas::Group      *range_marker_group;
 	ArdourCanvas::Group      *transport_marker_group;
 	ArdourCanvas::Group*      cd_marker_group;
-	
+
 	enum {
 		ruler_metric_smpte = 0,
 		ruler_metric_bbt = 1,
@@ -613,7 +613,7 @@
 	static GtkCustomMetric ruler_metrics[4];
 	bool                   ruler_shown[10];
 	bool                   no_ruler_shown_update;
-	
+
 	gint ruler_button_press (GdkEventButton*);
 	gint ruler_button_release (GdkEventButton*);
 	gint ruler_mouse_motion (GdkEventMotion*);
@@ -621,24 +621,24 @@
 
 	gint ruler_pressed_button;
 	Gtk::Widget * ruler_grabbed_widget;
-	
+
 	void initialize_rulers ();
 	void update_just_smpte ();
 	void compute_fixed_ruler_scale (); //calculates the RulerScale of the fixed rulers
 	void update_fixed_rulers ();
-	void update_tempo_based_rulers (); 
+	void update_tempo_based_rulers ();
 	void popup_ruler_menu (nframes_t where = 0, ItemType type = RegionItem);
 	void update_ruler_visibility ();
 	void ruler_toggled (int);
 	gint ruler_label_button_release (GdkEventButton*);
 	void store_ruler_visibility ();
 	void restore_ruler_visibility ();
-	
+
 	static gint _metric_get_smpte (GtkCustomRulerMark **, gdouble, gdouble, gint);
 	static gint _metric_get_bbt (GtkCustomRulerMark **, gdouble, gdouble, gint);
 	static gint _metric_get_frames (GtkCustomRulerMark **, gdouble, gdouble, gint);
 	static gint _metric_get_minsec (GtkCustomRulerMark **, gdouble, gdouble, gint);
-	
+
 	enum MinsecRulerScale {
 		minsec_show_seconds,
 		minsec_show_minutes,
@@ -707,14 +707,14 @@
 	static const double timebar_height;
 	guint32 visible_timebars;
 	Gtk::Menu          *editor_ruler_menu;
-	
+
 	ArdourCanvas::SimpleRect* tempo_bar;
 	ArdourCanvas::SimpleRect* meter_bar;
 	ArdourCanvas::SimpleRect* marker_bar;
 	ArdourCanvas::SimpleRect* range_marker_bar;
 	ArdourCanvas::SimpleRect* transport_marker_bar;
 	ArdourCanvas::SimpleRect* cd_marker_bar;
-	
+
 	Gtk::Label  minsec_label;
 	Gtk::Label  bbt_label;
 	Gtk::Label  smpte_label;
@@ -725,8 +725,8 @@
 	Gtk::Label  range_mark_label;
 	Gtk::Label  transport_mark_label;
 	Gtk::Label  cd_mark_label;
-	
 
+
 	Gtk::VBox          time_button_vbox;
 	Gtk::HBox          time_button_hbox;
 
@@ -785,7 +785,7 @@
 
 	Gtk::HBox           top_hbox;
 	Gtk::HBox           bottom_hbox;
-	
+
 	Gtk::Table          edit_packer;
 	Gtk::VScrollbar     edit_vscrollbar;
 
@@ -800,7 +800,7 @@
 	bool                _dragging_hscrollbar;
 
 	void reset_hscrollbar_stepping ();
-	
+
 	bool hscrollbar_button_press (GdkEventButton*);
 	bool hscrollbar_button_release (GdkEventButton*);
 	void hscrollbar_allocate (Gtk::Allocation &alloc);
@@ -831,7 +831,7 @@
 	void canvas_scroll_to (nframes64_t);
 
 	struct VisualChange {
-	    enum Type { 
+	    enum Type {
 		    TimeOrigin = 0x1,
 		    ZoomLevel = 0x2
 	    };
@@ -866,10 +866,10 @@
 	    Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Region> > region;
 	    Gtk::TreeModelColumn<Gdk::Color> color_;
 	};
-	    
+
 	RegionListDisplayModelColumns          region_list_columns;
 	Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Region> > region_list_display;
-	
+
 	Glib::RefPtr<Gtk::TreeStore>           region_list_model;
 	Glib::RefPtr<Gtk::ToggleAction>        toggle_full_region_list_action;
 	Glib::RefPtr<Gtk::ToggleAction>        toggle_show_auto_regions_action;
@@ -908,7 +908,7 @@
 
 	Gtk::ScrolledWindow snapshot_display_scroller;
 	struct SnapshotDisplayModelColumns : public Gtk::TreeModel::ColumnRecord {
-	    SnapshotDisplayModelColumns() { 
+	    SnapshotDisplayModelColumns() {
 		    add (visible_name);
 		    add (real_name);
 	    }
@@ -929,7 +929,7 @@
 	/* named selections */
 
 	struct NamedSelectionDisplayModelColumns : public Gtk::TreeModel::ColumnRecord {
-	    NamedSelectionDisplayModelColumns() { 
+	    NamedSelectionDisplayModelColumns() {
 		    add (text);
 		    add (selection);
 	    }
@@ -972,6 +972,7 @@
 	static Gdk::Cursor* speaker_cursor;
 	static Gdk::Cursor* midi_pencil_cursor;
 	static Gdk::Cursor* midi_select_cursor;
+	static Gdk::Cursor* midi_resize_cursor;
 	static Gdk::Cursor* midi_erase_cursor;
 	static Gdk::Cursor* wait_cursor;
 	static Gdk::Cursor* timebar_cursor;
@@ -983,9 +984,9 @@
 	nframes_t last_update_frame;
 	void center_screen (nframes_t);
 	void center_screen_internal (nframes_t, float);
-	
+
 	void update_current_screen ();
-	
+
 	void session_going_away ();
 
 	nframes_t cut_buffer_start;
@@ -997,7 +998,7 @@
 	bool motion_handler (ArdourCanvas::Item*, GdkEvent*, ItemType, bool from_autoscroll = false);
 	bool enter_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
 	bool leave_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
-	
+
 	/* KEYMAP HANDLING */
 
 	void register_actions ();
@@ -1025,7 +1026,7 @@
 	void paste_internal (nframes_t position, float times);
 
 	/* EDITING OPERATIONS */
-	
+
 	void reset_point_selection ();
 	void toggle_region_mute ();
 	void toggle_region_lock ();
@@ -1125,7 +1126,7 @@
 	void insert_route_list_drag (boost::shared_ptr<ARDOUR::Route>, int x, int y);
 
 	/* import & embed */
-	
+
 	void add_external_audio_action (Editing::ImportMode);
 	void external_audio_dialog ();
 
@@ -1133,7 +1134,7 @@
 	bool check_multichannel_status (const std::vector<Glib::ustring>& paths);
 
 	SoundFileOmega* sfbrowser;
-	
+
 	void bring_in_external_audio (Editing::ImportMode mode,  nframes64_t& pos);
 	void do_import (vector<Glib::ustring> paths, Editing::ImportDisposition, Editing::ImportMode mode, ARDOUR::SrcQuality, nframes64_t&);
 
@@ -1143,7 +1144,7 @@
 
 	int  import_sndfiles (vector<Glib::ustring> paths, Editing::ImportMode mode,  ARDOUR::SrcQuality, nframes64_t& pos,
 			      int target_regions, int target_tracks, boost::shared_ptr<ARDOUR::Track>&, bool);
-	int  embed_sndfiles (vector<Glib::ustring> paths, bool multiple_files, bool& check_sample_rate, Editing::ImportMode mode, 
+	int  embed_sndfiles (vector<Glib::ustring> paths, bool multiple_files, bool& check_sample_rate, Editing::ImportMode mode,
 			     nframes64_t& pos, int target_regions, int target_tracks, boost::shared_ptr<ARDOUR::Track>&);
 
 	int add_sources (vector<Glib::ustring> paths, ARDOUR::SourceList& sources, nframes64_t& pos, Editing::ImportMode,
@@ -1155,7 +1156,7 @@
 	boost::shared_ptr<ARDOUR::MidiTrack> get_nth_selected_midi_track (int nth) const;
 
 	/* generic interthread progress window */
-	
+
 	ArdourDialog* interthread_progress_window;
 	Gtk::Label interthread_progress_label;
 	Gtk::VBox interthread_progress_vbox;
@@ -1290,12 +1291,12 @@
 
 	void set_fade_in_shape (ARDOUR::AudioRegion::FadeShape);
 	void set_fade_out_shape (ARDOUR::AudioRegion::FadeShape);
-	
+
 	void set_fade_length (bool in);
 	void toggle_fade_active (bool in);
 	void set_fade_in_active (bool);
 	void set_fade_out_active (bool);
-	
+
 	std::set<boost::shared_ptr<ARDOUR::Playlist> > motion_frozen_playlists;
 	RegionSelection pre_drag_region_selection;
 	void region_drag_motion_callback (ArdourCanvas::Item*, GdkEvent*);
@@ -1367,8 +1368,8 @@
 	bool canvas_fade_in_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
 	bool canvas_fade_out_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
 	bool canvas_fade_out_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
-	
 
+
 	// These variables are used to detect a feedback loop and break it to avoid a gui hang
 private:
 	ArdourCanvas::Item *last_item_entered;
@@ -1435,7 +1436,7 @@
 	void reset_scrolling_region (Gtk::Allocation* alloc = 0);
 
 	/* display control */
-	
+
 	bool _show_measures;
 	/// true to show waveforms, otherwise false
 	bool _show_waveforms;
@@ -1443,12 +1444,12 @@
 	bool _follow_playhead;
 	/// true if waveforms should be shown while recording audio tracks, otherwise false
 	bool _show_waveforms_recording;
-	
+
 	ARDOUR::TempoMap::BBTPointList *current_bbt_points;
-	
+
 	ArdourCanvas::Group* time_line_group;
 	ArdourCanvas::Group* marker_time_line_group;
-	
+
 	TempoLines* tempo_lines;
 	TempoLines* marker_tempo_lines;
 
@@ -1465,12 +1466,12 @@
 	void remove_meter_marker (ArdourCanvas::Item*);
 	gint real_remove_tempo_marker (ARDOUR::TempoSection*);
 	gint real_remove_meter_marker (ARDOUR::MeterSection*);
-	
+
 	void edit_tempo_section (ARDOUR::TempoSection*);
 	void edit_meter_section (ARDOUR::MeterSection*);
 	void edit_tempo_marker (ArdourCanvas::Item*);
 	void edit_meter_marker (ArdourCanvas::Item*);
-	
+
 	void marker_menu_edit ();
 	void marker_menu_remove ();
 	void marker_menu_rename ();
@@ -1518,7 +1519,7 @@
 	int tempo_map_change_idle_handler_id;
 	void tempo_map_changed (ARDOUR::Change);
 	void redisplay_tempo (bool immediate_redraw);
-	
+
 	void snap_to (nframes64_t& first, int32_t direction = 0, bool for_mark = false);
 	void snap_to (nframes_t& first, int32_t direction = 0, bool for_mark = false) {
 		/* XXX remove this function when everything moves to 64 bit frame counts */
@@ -1526,13 +1527,13 @@
 		snap_to (first64, direction, for_mark);
 		first = (nframes_t) first64;
 	}
-	
+
 	double snap_length_beats (nframes_t start);
 
 	uint32_t bbt_beat_subdivision;
 
 	/* toolbar */
-	
+
 	Gtk::ToggleButton editor_mixer_button;
 	Gtk::ToggleButton editor_list_button;
 
@@ -1547,10 +1548,10 @@
 	Gtk::Button              zoom_onetoone_button;
 
 	Gtk::VBox                toolbar_clock_vbox;
-	Gtk::VBox                toolbar_selection_clock_vbox; 
+	Gtk::VBox                toolbar_selection_clock_vbox;
 	Gtk::Table               toolbar_selection_clock_table;
 	Gtk::Label               toolbar_selection_cursor_label;
-	
+
 	Gtk::HBox                mouse_mode_button_box;
 	Gtkmm2ext::TearOff*      mouse_mode_tearoff;
 	Gtk::ToggleButton        mouse_select_button;
@@ -1596,7 +1597,7 @@
 	Gtk::VBox         zoom_focus_box;
 
 	std::vector<std::string> zoom_focus_strings;
-	
+
 	void zoom_focus_selection_done ();
 	void zoom_focus_chosen (Editing::ZoomFocus);
 
@@ -1607,7 +1608,7 @@
 	void                zoom_adjustment_changed();
 
 	void                edit_point_clock_changed();
-	
+
 	void setup_toolbar ();
 
 	Gtkmm2ext::TearOff*      tools_tearoff;
@@ -1621,6 +1622,7 @@
 	Gtkmm2ext::TearOff*      midi_tool_tearoff;
 	Gtk::ToggleButton        midi_tool_pencil_button;
 	Gtk::ToggleButton        midi_tool_select_button;
+	Gtk::ToggleButton        midi_tool_resize_button;
 	Gtk::ToggleButton        midi_tool_erase_button;
 	GroupedButtons          *midi_tool_button_set;
 	void                     midi_edit_mode_toggled (Editing::MidiEditMode m);
@@ -1630,7 +1632,7 @@
 	Gtk::HBox           midi_toolbar_hbox;
 	Gtk::EventBox       midi_toolbar_base;
 	Gtk::Frame          midi_toolbar_frame;
-	
+
 	void setup_midi_toolbar ();
 
 	/* selection process */
@@ -1681,7 +1683,7 @@
 	ArdourCanvas::SimpleRect*  range_marker_drag_rect;
 
 	void update_marker_drag_item (ARDOUR::Location *);
-	
+
 	ArdourCanvas::SimpleRect     *transport_bar_range_rect;
 	ArdourCanvas::SimpleRect     *transport_bar_preroll_rect;
 	ArdourCanvas::SimpleRect     *transport_bar_postroll_rect;
@@ -1696,17 +1698,17 @@
 	ARDOUR::Location*  transport_punch_location();
 
 	ARDOUR::Location   *temp_location;
-	
+
 	/* object rubberband select process */
-	
+
 	void start_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event);
 	void drag_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event);
 	void end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event);
 
 	bool select_all_within (nframes_t start, nframes_t end, gdouble topy, gdouble boty, const TrackViewList&, Selection::Operation op);
-	
+
 	ArdourCanvas::SimpleRect   *rubberband_rect;
-	
+
 	/* mouse zoom process */
 
 	void start_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event);
@@ -1715,11 +1717,11 @@
 
 	ArdourCanvas::SimpleRect   *zoom_rect;
 	void reposition_zoom_rect (nframes_t start, nframes_t end);
-	
+
 	/* diskstream/route display management */
 
 	struct RouteDisplayModelColumns : public Gtk::TreeModel::ColumnRecord {
-	    RouteDisplayModelColumns() { 
+	    RouteDisplayModelColumns() {
 		    add (text);
 		    add (visible);
 		    add (tv);
@@ -1735,7 +1737,7 @@
 	Glib::RefPtr<Gtk::ListStore>     route_display_model;
 	Glib::RefPtr<Gtk::TreeSelection> route_display_selection;
 
-	Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Route> > route_list_display; 
+	Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Route> > route_list_display;
 	Gtk::ScrolledWindow                   route_list_scroller;
 	Gtk::Menu*                            route_list_menu;
 
@@ -1822,7 +1824,7 @@
 	int autoscroll_direction;
 	uint32_t autoscroll_cnt;
 	nframes_t autoscroll_distance;
-     
+
 	static gint _autoscroll_canvas (void *);
 	bool autoscroll_canvas ();
 	void start_canvas_autoscroll (int direction);
@@ -1874,7 +1876,7 @@
 						const Gtk::SelectionData& data,
 						guint               info,
 						guint               time);
-	
+
 	void  region_list_display_drag_data_received  (const Glib::RefPtr<Gdk::DragContext>& context,
 						       gint                x,
 						       gint                y,
@@ -1908,7 +1910,7 @@
 
 	ExportDialog *export_dialog;
 	ExportDialog *export_range_markers_dialog;
-	
+
 	void export_range (nframes_t start, nframes_t end);
 	void export_range_markers ();
 
@@ -1939,7 +1941,7 @@
 	UndoTransaction current_visual_command;
 
 
-	void update_title ();	
+	void update_title ();
 	void update_title_s (const string & snapshot_name);
 
 	struct State {
@@ -1956,7 +1958,7 @@
 	void instant_save ();
 
 	boost::shared_ptr<ARDOUR::AudioRegion> last_audition_region;
-	
+
 	/* freeze operations */
 
 	ARDOUR::InterThreadInfo freeze_status;
@@ -1975,7 +1977,7 @@
 	/* duplication */
 
 	void duplicate_dialog (bool with_dialog);
-	
+
 	nframes64_t event_frame (GdkEvent*, double* px = 0, double* py = 0) const;
 
 	/* returns false if mouse pointer is not in track or marker canvas
@@ -2058,7 +2060,7 @@
 	/* xfades */
 
 	bool _xfade_visibility;
-	
+
 #ifdef WITH_CMT
 	void handle_new_imageframe_time_axis_view(const string & track_name, void* src) ;
 	void handle_new_imageframe_marker_time_axis_view(const string & track_name, TimeAxisView* marked_track) ;
@@ -2086,7 +2088,7 @@
 	void imageframe_start_handle_end_trim(ArdourCanvas::Item* item, GdkEvent* event) ;
 	void imageframe_end_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* event) ;
 	void imageframe_end_handle_end_trim(ArdourCanvas::Item* item, GdkEvent* event) ;
-	
+
 	void markerview_item_start_handle_op(ArdourCanvas::Item* item, GdkEvent* event) ;
 	void markerview_item_end_handle_op(ArdourCanvas::Item* item, GdkEvent* event) ;
 	void markerview_start_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* event) ;
@@ -2121,7 +2123,7 @@
 
 	bool nudge_forward_release (GdkEventButton*);
 	bool nudge_backward_release (GdkEventButton*);
-	
+
 	/* audio filters */
 
 	void apply_filter (ARDOUR::Filter&, string cmd);
@@ -2188,7 +2190,7 @@
 
 	void get_regions_at (RegionSelection&, nframes64_t where, const TrackSelection& ts) const;
 	void get_regions_after (RegionSelection&, nframes64_t where, const TrackSelection& ts) const;
-	
+
 	void get_regions_for_action (RegionSelection&, bool allowed_entered_regionview = false);
 
 	sigc::connection fast_screen_update_connection;

hansfbaier

2008-03-16 23:22

reporter   ~0004787

fixed bug: snapto works on world coordinates, used it with region relative
added tool button for resizing

hansfbaier

2008-03-19 22:17

reporter   ~0004792

For the latest patch, please see http://tracker.ardour.org/view.php?id=2131
and dont use the above ones!

paul

2008-03-21 16:17

administrator   ~0004801

see notes - switched to 2131

hansfbaier

2008-03-24 01:44

reporter   ~0004807

I guess this one should still be opened since the latest fixes are not
yet committed.

Is there anything objectionable in the patches?

system

2020-04-19 20:13

developer   ~0021655

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
2008-03-14 23:05 hansfbaier New Issue
2008-03-14 23:05 hansfbaier File Added: resizing_midi_notes.diff
2008-03-15 00:38 drobilla Note Added: 0004777
2008-03-15 10:58 hansfbaier Note Added: 0004778
2008-03-15 10:59 hansfbaier File Added: bugfix_resizing_midi_notes.diff
2008-03-16 23:21 hansfbaier File Added: resizing_midi_notes_added_tool_and_fixed_snapto_bugs.diff
2008-03-16 23:22 hansfbaier Note Added: 0004787
2008-03-19 22:17 hansfbaier Note Added: 0004792
2008-03-21 16:17 paul Status new => resolved
2008-03-21 16:17 paul Resolution open => fixed
2008-03-21 16:17 paul Assigned To => paul
2008-03-21 16:17 paul Note Added: 0004801
2008-03-24 01:44 hansfbaier Status resolved => feedback
2008-03-24 01:44 hansfbaier Resolution fixed => reopened
2008-03-24 01:44 hansfbaier Note Added: 0004807
2008-05-22 01:08 drobilla Status feedback => resolved
2008-05-22 01:08 drobilla Resolution reopened => fixed
2020-04-19 20:13 system Note Added: 0021655
2020-04-19 20:13 system Status resolved => closed