diff --git a/SConstruct b/SConstruct
index be008c5c24..91e0bc0099 100644
--- a/SConstruct
+++ b/SConstruct
@@ -472,6 +472,16 @@ libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
libraries['samplerate'] = LibraryInfo()
libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
+libraries['rubberband'] = LibraryInfo()
+#
+# chris cannam's rubberband has not yet been released
+#
+if os.path.exists ('libs/rubberband'):
+ libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
+ LIBPATH='#libs/rubberband/lib',
+ CPPPATH='#libs/rubberband/src',
+ CXXFLAGS='-DUSE_RUBBERBAND')
+
if env['FFT_ANALYSIS']:
libraries['fftw3f'] = LibraryInfo()
libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript
index b1c6a6b75c..04ebf15f5b 100644
--- a/gtk2_ardour/SConscript
+++ b/gtk2_ardour/SConscript
@@ -50,6 +50,7 @@ gtkardour.Merge ([
libraries['xml'],
libraries['xslt'],
libraries['soundtouch'],
+ libraries['rubberband'],
libraries['samplerate'],
libraries['jack']
])
diff --git a/gtk2_ardour/ardour-sae.menus b/gtk2_ardour/ardour-sae.menus
index 111678429f..47bd89801c 100644
--- a/gtk2_ardour/ardour-sae.menus
+++ b/gtk2_ardour/ardour-sae.menus
@@ -79,25 +79,6 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index c627e8da63..25657e36f4 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -403,7 +403,10 @@ class Editor : public PublicEditor
struct LocationMarkers {
Marker* start;
Marker* end;
+ bool valid;
+ LocationMarkers () : start(0), end(0), valid (true) {}
+
~LocationMarkers ();
void hide();
@@ -906,6 +909,7 @@ class Editor : public PublicEditor
void split_region_at (nframes_t);
void split_regions_at (nframes_t, RegionSelection&);
void crop_region_to_selection ();
+ void crop_region_to (nframes_t start, nframes_t end);
void set_a_regions_sync_position (boost::shared_ptr, nframes_t);
void set_region_sync_from_edit_point ();
void remove_region_sync();
@@ -1922,6 +1926,8 @@ class Editor : public PublicEditor
Glib::RefPtr edit_point_action (Editing::EditPoint);
std::vector edit_point_strings;
+ bool get_edit_op_range (nframes64_t& start, nframes64_t& end) const;
+
RegionSelection get_regions_at (nframes64_t where, const TrackSelection& ts) const;
};
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index 3742edcf70..937d83c7c8 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -45,6 +45,7 @@ Editor::register_actions ()
/* non-operative menu items for menu bar */
ActionManager::register_action (editor_actions, X_("Edit"), _("Edit"));
+ ActionManager::register_action (editor_actions, X_("Select"), _("Select"));
ActionManager::register_action (editor_actions, X_("EditSelectRegionOptions"), _("Select Regions"));
ActionManager::register_action (editor_actions, X_("EditSelectRangeOptions"), _("Select Range Operations"));
ActionManager::register_action (editor_actions, X_("EditCursorMovementOptions"), _("Move Selected Marker"));
diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc
index 772e5fd038..3e0868e048 100644
--- a/gtk2_ardour/editor_markers.cc
+++ b/gtk2_ardour/editor_markers.cc
@@ -223,11 +223,43 @@ Editor::find_location_from_marker (Marker *marker, bool& is_start) const
void
Editor::refresh_location_display_internal (Locations::LocationList& locations)
{
- clear_marker_display ();
+ /* invalidate all */
+
+ for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
+ i->second->valid = false;
+ }
+ /* add new ones */
+
for (Locations::LocationList::iterator i = locations.begin(); i != locations.end(); ++i) {
+
+ LocationMarkerMap::iterator x;
+
+ if ((x = location_markers.find (*i)) != location_markers.end()) {
+ x->second->valid = true;
+ continue;
+ }
+
add_new_location (*i);
}
+
+ /* remove dead ones */
+
+ for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ) {
+
+ LocationMarkerMap::iterator tmp;
+
+ tmp = i;
+ ++tmp;
+
+ if (!i->second->valid) {
+ delete i->second;
+ location_markers.erase (i);
+ }
+
+ i = tmp;
+ }
+
}
void
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 442397f4f8..73681bd62c 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -2323,16 +2323,37 @@ Editor::separate_regions_using_location (Location& loc)
void
Editor::crop_region_to_selection ()
{
- if (selection->time.empty() || selection->tracks.empty()) {
- return;
- }
+ if (!selection->time.empty()) {
+ crop_region_to (selection->time.start(), selection->time.end_frame());
+
+ } else if (_edit_point != EditAtPlayhead) {
+
+ nframes64_t start;
+ nframes64_t end;
+
+ if (get_edit_op_range (start, end)) {
+ crop_region_to (start, end);
+ }
+ }
+
+}
+
+void
+Editor::crop_region_to (nframes_t start, nframes_t end)
+{
vector > playlists;
boost::shared_ptr playlist;
+ TrackSelection* ts;
- sort_track_selection ();
+ if (selection->tracks.empty()) {
+ ts = &track_views;
+ } else {
+ sort_track_selection ();
+ ts = &selection->tracks;
+ }
- for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+ for (TrackSelection::iterator i = ts->begin(); i != ts->end(); ++i) {
AudioTimeAxisView* atv;
@@ -2357,8 +2378,8 @@ Editor::crop_region_to_selection ()
return;
}
- nframes_t start;
- nframes_t end;
+ nframes_t the_start;
+ nframes_t the_end;
nframes_t cnt;
begin_reversible_command (_("trim to selection"));
@@ -2366,10 +2387,10 @@ Editor::crop_region_to_selection ()
for (vector >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
boost::shared_ptr region;
-
- start = selection->time.start();
-
- if ((region = (*i)->top_region_at(start)) == 0) {
+
+ the_start = start;
+
+ if ((region = (*i)->top_region_at(the_start)) == 0) {
continue;
}
@@ -2377,17 +2398,17 @@ Editor::crop_region_to_selection ()
if the selection extends beyond the region
*/
- start = max (start, region->position());
- if (max_frames - start < region->length()) {
- end = start + region->length() - 1;
+ the_start = max (the_start, region->position());
+ if (max_frames - the_start < region->length()) {
+ the_end = the_start + region->length() - 1;
} else {
- end = max_frames;
+ the_end = max_frames;
}
- end = min (selection->time.end_frame(), end);
- cnt = end - start + 1;
+ the_end = min (end, the_end);
+ cnt = the_end - the_start + 1;
XMLNode &before = (*i)->get_state();
- region->trim_to (start, cnt, this);
+ region->trim_to (the_start, cnt, this);
XMLNode &after = (*i)->get_state();
session->add_command (new MementoCommand(*(*i), &before, &after));
}
@@ -2927,21 +2948,31 @@ Editor::cut_copy (CutCopyOp op)
}
commit_reversible_command ();
+ break; // terminate case statement here
+ }
+ if (!selection->time.empty()) {
+ /* don't cause suprises */
+ break;
}
- break;
+ // fall thru if there was nothing selected
case MouseRange:
- if (!selection->time.empty()) {
-
- begin_reversible_command (opname + _(" range"));
- cut_copy_ranges (op);
- commit_reversible_command ();
-
- if (op == Cut) {
- selection->clear_time ();
+ if (selection->time.empty()) {
+ nframes64_t start, end;
+ if (!get_edit_op_range (start, end)) {
+ return;
}
-
+ selection->set (0, start, end);
}
+
+ begin_reversible_command (opname + _(" range"));
+ cut_copy_ranges (op);
+ commit_reversible_command ();
+
+ if (op == Cut) {
+ selection->clear_time ();
+ }
+
break;
default:
diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
index 91d3a3b939..9f825b0a51 100644
--- a/gtk2_ardour/editor_selection.cc
+++ b/gtk2_ardour/editor_selection.cc
@@ -1040,29 +1040,17 @@ Editor::select_all_selectables_between (bool within)
nframes64_t end;
list touched;
- if (_edit_point == EditAtPlayhead) {
+ if (!get_edit_op_range (start, end)) {
return;
}
- start = get_preferred_edit_position();
- end = playhead_cursor->current_frame;
-
- if (start == end) {
- return;
- }
-
- if (start > end) {
- swap (start, end);
- }
-
- end -= 1;
-
for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
if ((*iter)->hidden()) {
continue;
}
(*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
}
+
selection->set (touched);
}
@@ -1071,25 +1059,70 @@ Editor::select_range_between ()
{
nframes64_t start;
nframes64_t end;
- list touched;
-
- if (_edit_point == EditAtPlayhead) {
+
+ if (!get_edit_op_range (start, end)) {
return;
}
-
- start = get_preferred_edit_position();
- end = playhead_cursor->current_frame;
+
+ set_mouse_mode (MouseRange);
+ selection->set (0, start, end);
+}
+
+bool
+Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
+{
+ nframes64_t m;
+ bool ignored;
+
+ /* in range mode, use any existing selection */
+
+ if (mouse_mode == MouseRange && !selection->time.empty()) {
+ /* we know that these are ordered */
+ start = selection->time.start();
+ end = selection->time.end_frame();
+ return true;
+ }
+
+ if (!mouse_frame (m, ignored)) {
+ /* mouse is not in a canvas, try playhead+selected marker.
+ this is probably most true when using menus.
+ */
+
+ if (selection->markers.empty()) {
+ return false;
+ }
+
+ start = selection->markers.front()->position();
+ end = session->audible_frame();
+
+ } else {
+
+ switch (_edit_point) {
+ case EditAtPlayhead:
+ /* use mouse + playhead */
+ start = m;
+ end = session->audible_frame();
+ break;
+
+ case EditAtMouse:
+ case EditAtSelectedMarker:
+ /* use mouse + selected marker */
+ if (selection->markers.empty()) {
+ return false;
+ }
+ start = selection->markers.front()->position();
+ end = m;
+ break;
+ }
+ }
if (start == end) {
- return;
+ return false;
}
if (start > end) {
swap (start, end);
}
- end -= 1;
-
- set_mouse_mode (MouseRange);
- selection->set (0, start, end);
+ return true;
}