diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 6d55327e45..72997a9ad0 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -2566,8 +2566,8 @@ Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark) void Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark) { - Location* before = 0; - Location* after = 0; + nframes64_t before; + nframes64_t after; const nframes64_t one_second = session->frame_rate(); const nframes64_t one_minute = session->frame_rate() * 60; @@ -2682,39 +2682,21 @@ Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark) return; } - before = session->locations()->first_location_before (start); - after = session->locations()->first_location_after (start); + session->locations()->marks_either_side (start, before, after); - if (direction < 0) { - if (before) { - start = before->start(); + if (before == max_frames) { + start = after; + } else if (after == max_frames) { + start = before; + } else if (before != max_frames && after != max_frames) { + /* have before and after */ + if ((start - before) < (after - start)) { + start = before; } else { - start = 0; - } - } else if (direction > 0) { - if (after) { - start = after->start(); - } else { - start = session->current_end_frame(); - } - } else { - if (before) { - if (after) { - /* find nearest of the two */ - if ((start - before->start()) < (after->start() - start)) { - start = before->start(); - } else { - start = after->start(); - } - } else { - start = before->start(); - } - } else if (after) { - start = after->start(); - } else { - /* relax */ + start = after; } } + break; case SnapToRegionStart: diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index e6e944bc3b..81f210a901 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -3238,14 +3238,13 @@ RangeMarkerBarDrag::finished (GdkEvent* event, bool movement_occurred) nframes64_t start; nframes64_t end; - start = _editor->session->locations()->first_mark_before (_grab_frame); - end = _editor->session->locations()->first_mark_after (_grab_frame); + _editor->session->locations()->marks_either_side (_grab_frame, start, end); if (end == max_frames) { end = _editor->session->current_end_frame (); } - if (start == 0) { + if (start == max_frames) { start = _editor->session->current_start_frame (); } diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc index b95c29ee42..7bd09379d8 100644 --- a/gtk2_ardour/editor_markers.cc +++ b/gtk2_ardour/editor_markers.cc @@ -827,7 +827,9 @@ Editor::marker_menu_range_to_next () return; } - nframes_t end = session->locations()->first_mark_after (marker->position()); + nframes64_t start; + nframes64_t end; + session->locations()->marks_either_side (marker->position(), start, end); if (end != max_frames) { string range_name = l->name(); diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h index b48db52d92..149a559d85 100644 --- a/libs/ardour/ardour/location.h +++ b/libs/ardour/ardour/location.h @@ -172,8 +172,7 @@ class Locations : public PBD::StatefulDestructible Location *first_location_before (nframes64_t, bool include_special_ranges = false); Location *first_location_after (nframes64_t, bool include_special_ranges = false); - nframes64_t first_mark_before (nframes64_t, bool include_special_ranges = false); - nframes64_t first_mark_after (nframes64_t, bool include_special_ranges = false); + void marks_either_side (nframes64_t const, nframes64_t &, nframes64_t &) const; void find_all_between (nframes64_t start, nframes64_t, LocationList&, Location::Flags); diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc index 02d355d915..b3421d2b0b 100644 --- a/libs/ardour/location.cc +++ b/libs/ardour/location.cc @@ -23,6 +23,8 @@ #include #include #include +#include + #include #include "pbd/stl_delete.h" @@ -786,84 +788,67 @@ Locations::first_location_after (nframes64_t frame, bool include_special_ranges) return 0; } -nframes64_t -Locations::first_mark_before (nframes64_t frame, bool include_special_ranges) +/** Look for the `marks' (either locations which are marks, or start/end points of range markers) either + * side of a frame. + * @param frame Frame to look for. + * @param before Filled in with the position of the last `mark' before `frame' (or max_frames if none exists) + * @param after Filled in with the position of the last `mark' after `frame' (or max_frames if none exists) + */ +void +Locations::marks_either_side (nframes64_t const frame, nframes64_t& before, nframes64_t& after) const { + before = after = max_frames; + LocationList locs; { - Glib::Mutex::Lock lm (lock); + Glib::Mutex::Lock lm (lock); locs = locations; } - LocationStartLaterComparison cmp; - locs.sort (cmp); + std::list positions; - /* locs is now sorted latest..earliest */ - - for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) { - if (!include_special_ranges && ((*i)->is_auto_loop() || (*i)->is_auto_punch())) { + for (LocationList::const_iterator i = locs.begin(); i != locs.end(); ++i) { + if (((*i)->is_auto_loop() || (*i)->is_auto_punch())) { continue; } + if (!(*i)->is_hidden()) { - if ((*i)->is_mark()) { - /* MARK: start == end */ - if ((*i)->start() < frame) { - return (*i)->start(); - } + if ((*i)->is_mark ()) { + positions.push_back ((*i)->start ()); } else { - /* RANGE: start != end, compare start and end */ - if ((*i)->end() < frame) { - return (*i)->end(); - } - if ((*i)->start () < frame) { - return (*i)->start(); - } + positions.push_back ((*i)->start ()); + positions.push_back ((*i)->end ()); } } } - return 0; -} - -nframes64_t -Locations::first_mark_after (nframes64_t frame, bool include_special_ranges) -{ - LocationList locs; - - { - Glib::Mutex::Lock lm (lock); - locs = locations; + if (positions.empty ()) { + return; } - LocationStartEarlierComparison cmp; - locs.sort (cmp); + positions.sort (); - /* locs is now sorted earliest..latest */ - - for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) { - if (!include_special_ranges && ((*i)->is_auto_loop() || (*i)->is_auto_punch())) { - continue; - } - if (!(*i)->is_hidden()) { - if ((*i)->is_mark()) { - /* MARK, start == end so just compare start */ - if ((*i)->start() > frame) { - return (*i)->start(); - } - } else { - /* RANGE, start != end, compare start and end */ - if ((*i)->start() > frame ) { - return (*i)->start (); - } - if ((*i)->end() > frame) { - return (*i)->end (); - } - } - } + std::list::iterator i = positions.begin (); + while (i != positions.end () && *i < frame) { + ++i; } - return max_frames; + if (i == positions.end ()) { + /* run out of marks */ + before = positions.back (); + return; + } + + after = *i; + + if (i == positions.begin ()) { + /* none before */ + return; + } + + --i; + before = *i; } Location*