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;
}
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) {
_session->request_locate (location->start(), _session->transport_rolling());
} else {
_session->request_locate (_session->current_end_frame());
if (pos < 0) {
return;
}
_session->request_locate (pos, _session->transport_rolling());
}
void
@ -1862,13 +1862,13 @@ Editor::jump_backward_to_mark ()
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) {
_session->request_locate (location->start(), _session->transport_rolling());
} else {
_session->goto_start ();
if (pos < 0) {
return;
}
_session->request_locate (pos, _session->transport_rolling());
}
void

View File

@ -161,8 +161,8 @@ class Locations : public SessionHandleRef, public PBD::StatefulDestructible
int set_current (Location *, bool want_lock = true);
Location *current () const { return current_location; }
Location* first_location_before (framepos_t, bool include_special_ranges = false);
Location* first_location_after (framepos_t, bool include_special_ranges = false);
framepos_t first_mark_before (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;

View File

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

View File

@ -171,10 +171,10 @@ BasicUI::save_state ()
void
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) {
session->request_locate (location->start(), session->transport_rolling());
if (pos >= 0) {
session->request_locate (pos, session->transport_rolling());
} else {
session->goto_start ();
}
@ -183,12 +183,12 @@ BasicUI::prev_marker ()
void
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) {
session->request_locate (location->start(), session->transport_rolling());
if (pos >= 0) {
session->request_locate (pos, session->transport_rolling());
} 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
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
if (session->transport_rolling() && elapsed < 500 && loc != 0) {
Location * loc_two_back = session->locations()->first_location_before (loc->start());
if (loc_two_back != 0)
{
loc = loc_two_back;
if (session->transport_rolling() && elapsed < 500 && pos >= 0) {
framepos_t pos_two_back = session->locations()->first_mark_before (pos);
if (pos_two_back >= 0) {
pos = pos_two_back;
}
}
// move to the location, if it's valid
if (loc != 0) {
session->request_locate (loc->start(), session->transport_rolling());
if (pos >= 0) {
session->request_locate (pos, session->transport_rolling());
} 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;
@ -460,12 +459,12 @@ LedState
MackieControlProtocol::frm_right_press (Button &)
{
// 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) {
session->request_locate (loc->start(), session->transport_rolling());
if (pos >= 0) {
session->request_locate (pos, session->transport_rolling());
} 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;