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 @@ - - - - - - - - - - - - - - - - - - - @@ -124,6 +105,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus index d6f40a3fff..15865e273a 100644 --- a/gtk2_ardour/ardour.menus +++ b/gtk2_ardour/ardour.menus @@ -80,25 +80,6 @@ - - - - - - - - - - - - - - - - - - - @@ -111,24 +92,6 @@ - - - - - - - - - - - - - - - - - - @@ -145,6 +108,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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; }