fix up Location::first_location_(after|before) to do the right thing when marks + ranges are interleaved (functions renamed)

git-svn-id: svn://localhost/ardour2/branches/3.0@13869 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2013-01-17 13:19:16 +00:00
parent 53f162f921
commit 4ecb07aaee
5 changed files with 79 additions and 65 deletions

View file

@ -1846,13 +1846,13 @@ Editor::jump_forward_to_mark ()
return; return;
} }
Location *location = _session->locations()->first_location_after (playhead_cursor->current_frame); framepos_t pos = _session->locations()->first_mark_after (playhead_cursor->current_frame);
if (location) { if (pos < 0) {
_session->request_locate (location->start(), _session->transport_rolling()); return;
} else {
_session->request_locate (_session->current_end_frame());
} }
_session->request_locate (pos, _session->transport_rolling());
} }
void void
@ -1862,13 +1862,13 @@ Editor::jump_backward_to_mark ()
return; return;
} }
Location *location = _session->locations()->first_location_before (playhead_cursor->current_frame); framepos_t pos = _session->locations()->first_mark_before (playhead_cursor->current_frame);
if (location) { if (pos < 0) {
_session->request_locate (location->start(), _session->transport_rolling()); return;
} else {
_session->goto_start ();
} }
_session->request_locate (pos, _session->transport_rolling());
} }
void void

View file

@ -161,8 +161,8 @@ class Locations : public SessionHandleRef, public PBD::StatefulDestructible
int set_current (Location *, bool want_lock = true); int set_current (Location *, bool want_lock = true);
Location *current () const { return current_location; } Location *current () const { return current_location; }
Location* first_location_before (framepos_t, bool include_special_ranges = false); framepos_t first_mark_before (framepos_t, bool include_special_ranges = false);
Location* first_location_after (framepos_t, bool include_special_ranges = false); framepos_t first_mark_after (framepos_t, bool include_special_ranges = false);
void marks_either_side (framepos_t const, framepos_t &, framepos_t &) const; void marks_either_side (framepos_t const, framepos_t &, framepos_t &) const;

View file

@ -922,72 +922,87 @@ Locations::set_state (const XMLNode& node, int version)
return 0; return 0;
} }
typedef std::pair<framepos_t,Location*> LocationPair;
struct LocationStartEarlierComparison struct LocationStartEarlierComparison
{ {
bool operator() (Location *a, Location *b) { bool operator() (LocationPair a, LocationPair b) {
return a->start() < b->start(); return a.first < b.first;
} }
}; };
struct LocationStartLaterComparison struct LocationStartLaterComparison
{ {
bool operator() (Location *a, Location *b) { bool operator() (LocationPair a, LocationPair b) {
return a->start() > b->start(); return a.first > b.first;
} }
}; };
Location * framepos_t
Locations::first_location_before (framepos_t frame, bool include_special_ranges) Locations::first_mark_before (framepos_t frame, bool include_special_ranges)
{ {
LocationList locs; Glib::Threads::Mutex::Lock lm (lock);
vector<LocationPair> locs;
{
Glib::Threads::Mutex::Lock lm (lock); for (LocationList::iterator i = locations.begin(); i != locations.end(); ++i) {
locs = locations; locs.push_back (make_pair ((*i)->start(), (*i)));
if (!(*i)->is_mark()) {
locs.push_back (make_pair ((*i)->end(), (*i)));
}
} }
LocationStartLaterComparison cmp; LocationStartLaterComparison cmp;
locs.sort (cmp); sort (locs.begin(), locs.end(), cmp);
/* locs is now sorted latest..earliest */ /* locs is sorted in ascending order */
for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) { for (vector<LocationPair>::iterator i = locs.begin(); i != locs.end(); ++i) {
if (!include_special_ranges && ((*i)->is_auto_loop() || (*i)->is_auto_punch())) { if ((*i).second->is_hidden()) {
continue; continue;
} }
if (!(*i)->is_hidden() && (*i)->start() < frame) { if (!include_special_ranges && ((*i).second->is_auto_loop() || (*i).second->is_auto_punch())) {
return (*i); continue;
}
if ((*i).first < frame) {
return (*i).first;
} }
} }
return 0; return -1;
} }
Location * framepos_t
Locations::first_location_after (framepos_t frame, bool include_special_ranges) Locations::first_mark_after (framepos_t frame, bool include_special_ranges)
{ {
LocationList locs; Glib::Threads::Mutex::Lock lm (lock);
vector<LocationPair> locs;
{ for (LocationList::iterator i = locations.begin(); i != locations.end(); ++i) {
Glib::Threads::Mutex::Lock lm (lock); locs.push_back (make_pair ((*i)->start(), (*i)));
locs = locations; if (!(*i)->is_mark()) {
locs.push_back (make_pair ((*i)->end(), (*i)));
}
} }
LocationStartEarlierComparison cmp; LocationStartEarlierComparison cmp;
locs.sort (cmp); sort (locs.begin(), locs.end(), cmp);
/* locs is sorted in reverse order */
/* locs is now sorted earliest..latest */ for (vector<LocationPair>::iterator i = locs.begin(); i != locs.end(); ++i) {
if ((*i).second->is_hidden()) {
for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) {
if (!include_special_ranges && ((*i)->is_auto_loop() || (*i)->is_auto_punch())) {
continue; continue;
} }
if (!(*i)->is_hidden() && (*i)->start() > frame) { if (!include_special_ranges && ((*i).second->is_auto_loop() || (*i).second->is_auto_punch())) {
return (*i); continue;
}
if ((*i).first > frame) {
return (*i).first;
} }
} }
return 0; return -1;
} }
/** Look for the `marks' (either locations which are marks, or start/end points of range markers) either /** Look for the `marks' (either locations which are marks, or start/end points of range markers) either

View file

@ -171,10 +171,10 @@ BasicUI::save_state ()
void void
BasicUI::prev_marker () BasicUI::prev_marker ()
{ {
Location *location = session->locations()->first_location_before (session->transport_frame()); framepos_t pos = session->locations()->first_mark_before (session->transport_frame());
if (location) { if (pos >= 0) {
session->request_locate (location->start(), session->transport_rolling()); session->request_locate (pos, session->transport_rolling());
} else { } else {
session->goto_start (); session->goto_start ();
} }
@ -183,12 +183,12 @@ BasicUI::prev_marker ()
void void
BasicUI::next_marker () BasicUI::next_marker ()
{ {
Location *location = session->locations()->first_location_after (session->transport_frame()); framepos_t pos = session->locations()->first_mark_after (session->transport_frame());
if (location) { if (pos >= 0) {
session->request_locate (location->start(), session->transport_rolling()); session->request_locate (pos, session->transport_rolling());
} else { } else {
session->request_locate (session->current_end_frame()); session->goto_end();
} }
} }

View file

@ -429,22 +429,21 @@ MackieControlProtocol::frm_left_press (Button &)
// can use first_mark_before/after as well // can use first_mark_before/after as well
unsigned long elapsed = _frm_left_last.restart(); unsigned long elapsed = _frm_left_last.restart();
Location * loc = session->locations()->first_location_before (session->transport_frame()); framepos_t pos = session->locations()->first_mark_before (session->transport_frame());
// allow a quick double to go past a previous mark // allow a quick double to go past a previous mark
if (session->transport_rolling() && elapsed < 500 && loc != 0) { if (session->transport_rolling() && elapsed < 500 && pos >= 0) {
Location * loc_two_back = session->locations()->first_location_before (loc->start()); framepos_t pos_two_back = session->locations()->first_mark_before (pos);
if (loc_two_back != 0) if (pos_two_back >= 0) {
{ pos = pos_two_back;
loc = loc_two_back;
} }
} }
// move to the location, if it's valid // move to the location, if it's valid
if (loc != 0) { if (pos >= 0) {
session->request_locate (loc->start(), session->transport_rolling()); session->request_locate (pos, session->transport_rolling());
} else { } else {
session->request_locate (session->locations()->session_range_location()->start(), session->transport_rolling()); session->request_locate (session->current_start_frame(), session->transport_rolling());
} }
return on; return on;
@ -460,12 +459,12 @@ LedState
MackieControlProtocol::frm_right_press (Button &) MackieControlProtocol::frm_right_press (Button &)
{ {
// can use first_mark_before/after as well // can use first_mark_before/after as well
Location * loc = session->locations()->first_location_after (session->transport_frame()); framepos_t pos = session->locations()->first_mark_after (session->transport_frame());
if (loc != 0) { if (pos >= 0) {
session->request_locate (loc->start(), session->transport_rolling()); session->request_locate (pos, session->transport_rolling());
} else { } else {
session->request_locate (session->locations()->session_range_location()->end(), session->transport_rolling()); session->request_locate (session->current_end_frame(), session->transport_rolling());
} }
return on; return on;