first pass at making shift-click to select region extend the selection vertically across tracks

git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2809 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2007-12-21 20:34:55 +00:00
parent ed1283568b
commit bae8d50093
7 changed files with 176 additions and 39 deletions

View file

@ -67,6 +67,7 @@
; (gtk_accel_path "<Actions>/Main/AudioFileFormatData" "")
; (gtk_accel_path "<Actions>/options/MeterFalloffFastest" "")
(gtk_accel_path "<Actions>/Editor/play-selected-regions" "w")
(gtk_accel_path "<Actions>/Editor/play-edit-range" "<%SECONDARY%>w")
(gtk_accel_path "<Actions>/Transport/Forward" "<%PRIMARY%>rightarrow")
; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-seconds" "")
; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-frame" "")

View file

@ -31,6 +31,7 @@
<menu name='Transport' action='Transport'>
<menuitem action='ToggleRoll'/>
<menuitem action='play-from-edit-point-and-return'/>
<menuitem action='play-edit-range'/>
<menuitem action='record-roll'/>
<menuitem action='ToggleRollForgetCapture'/>
<menuitem action='Loop'/>

View file

@ -33,6 +33,7 @@
<menuitem action='ToggleRollForgetCapture'/>
<menuitem action='Loop'/>
<menuitem action='PlaySelection'/>
<menuitem action='play-edit-range'/>
<menuitem action='Forward'/>
<menuitem action='Rewind'/>
<menuitem action='GotoZero'/>

View file

@ -1001,6 +1001,7 @@ class Editor : public PublicEditor
void play_from_edit_point ();
void play_from_edit_point_and_return ();
void play_selected_region ();
void play_edit_range ();
void loop_selected_region ();
void play_location (ARDOUR::Location&);
void loop_location (ARDOUR::Location&);

View file

@ -300,6 +300,7 @@ Editor::register_actions ()
act = ActionManager::register_action (editor_actions, "play-from-edit-point-and-return", _("Play from Edit Point & Return"), mem_fun(*this, &Editor::play_from_edit_point_and_return));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "play-edit-range", _("Play Edit Range"), mem_fun(*this, &Editor::play_edit_range));
act = ActionManager::register_action (editor_actions, "play-selected-regions", _("Play Selected Region(s)"), mem_fun(*this, &Editor::play_selected_region));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "brush-at-mouse", _("Brush at Mouse"), mem_fun(*this, &Editor::kbd_brush));

View file

@ -2364,6 +2364,16 @@ Editor::audition_playlist_region_via_route (boost::shared_ptr<Region> region, Ro
/* XXX how to unset the solo state ? */
}
void
Editor::play_edit_range ()
{
nframes64_t start, end;
if (get_edit_op_range (start, end)) {
session->request_bounded_roll (start, end);
}
}
void
Editor::play_selected_region ()
{

View file

@ -17,6 +17,9 @@
*/
#include <algorithm>
#include <stdlib.h>
#include <pbd/stacktrace.h>
#include <ardour/diskstream.h>
@ -464,6 +467,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
list<Selectable*> results;
nframes_t last_frame;
nframes_t first_frame;
bool same_track = false;
/* 1. find the last selected regionview in the track that was clicked in */
@ -480,63 +484,181 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
if ((*x)->region()->first_frame() < first_frame) {
first_frame = (*x)->region()->first_frame();
}
same_track = true;
}
}
/* 2. figure out the boundaries for our search for new objects */
if (same_track) {
switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
case OverlapNone:
if (last_frame < clicked_regionview->region()->first_frame()) {
first_frame = last_frame;
last_frame = clicked_regionview->region()->last_frame();
} else {
last_frame = first_frame;
first_frame = clicked_regionview->region()->first_frame();
/* 2. figure out the boundaries for our search for new objects */
switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
case OverlapNone:
if (last_frame < clicked_regionview->region()->first_frame()) {
first_frame = last_frame;
last_frame = clicked_regionview->region()->last_frame();
} else {
last_frame = first_frame;
first_frame = clicked_regionview->region()->first_frame();
}
break;
case OverlapExternal:
if (last_frame < clicked_regionview->region()->first_frame()) {
first_frame = last_frame;
last_frame = clicked_regionview->region()->last_frame();
} else {
last_frame = first_frame;
first_frame = clicked_regionview->region()->first_frame();
}
break;
case OverlapInternal:
if (last_frame < clicked_regionview->region()->first_frame()) {
first_frame = last_frame;
last_frame = clicked_regionview->region()->last_frame();
} else {
last_frame = first_frame;
first_frame = clicked_regionview->region()->first_frame();
}
break;
case OverlapStart:
case OverlapEnd:
/* nothing to do except add clicked region to selection, since it
overlaps with the existing selection in this track.
*/
break;
}
break;
case OverlapExternal:
if (last_frame < clicked_regionview->region()->first_frame()) {
first_frame = last_frame;
last_frame = clicked_regionview->region()->last_frame();
} else {
last_frame = first_frame;
first_frame = clicked_regionview->region()->first_frame();
}
break;
} else {
case OverlapInternal:
if (last_frame < clicked_regionview->region()->first_frame()) {
first_frame = last_frame;
last_frame = clicked_regionview->region()->last_frame();
} else {
last_frame = first_frame;
first_frame = clicked_regionview->region()->first_frame();
}
break;
case OverlapStart:
case OverlapEnd:
/* nothing to do except add clicked region to selection, since it
overlaps with the existing selection in this track.
/* click in a track that has no regions selected, so extend vertically
to pick out all regions that are defined by the existing selection
plus this one.
*/
break;
first_frame = entered_regionview->region()->position();
last_frame = entered_regionview->region()->last_frame();
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
if ((*i)->region()->position() < first_frame) {
first_frame = (*i)->region()->position();
}
if ((*i)->region()->last_frame() + 1 > last_frame) {
last_frame = (*i)->region()->last_frame();
}
}
}
/* 2. find all selectable objects (regionviews in this case) between that one and the end of the
one that was clicked.
*/
/* 2. find all the tracks we should select in */
set<AudioTimeAxisView*> relevant_tracks;
set<AudioTimeAxisView*> already_in_selection;
get_relevant_audio_tracks (relevant_tracks);
if (relevant_tracks.empty()) {
/* no relevant tracks -> no tracks selected .. thus .. if
the regionview we're in isn't selected (i.e. we're
about to extend to it), then find all tracks between
the this one and any selected ones.
*/
if (!selection->selected (entered_regionview)) {
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&entered_regionview->get_time_axis_view());
if (atv) {
/* add this track to the ones we will search */
relevant_tracks.insert (atv);
/* find the track closest to this one that
already a selected region.
*/
AudioTimeAxisView* closest = 0;
int distance = INT_MAX;
int key = atv->route()->order_key ("editor");
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
AudioTimeAxisView* aatv = dynamic_cast<AudioTimeAxisView*>(&(*x)->get_time_axis_view());
if (aatv && aatv != atv) {
pair<set<AudioTimeAxisView*>::iterator,bool> result;
result = already_in_selection.insert (aatv);
if (result.second) {
/* newly added to already_in_selection */
int d = aatv->route()->order_key ("editor");
d -= key;
if (abs (d) < distance) {
distance = abs (d);
closest = aatv;
}
}
}
}
if (closest) {
/* now add all tracks between that one and this one */
int okey = closest->route()->order_key ("editor");
if (okey > key) {
swap (okey, key);
}
for (TrackViewList::iterator x = track_views.begin(); x != track_views.end(); ++x) {
AudioTimeAxisView* aatv = dynamic_cast<AudioTimeAxisView*>(*x);
if (aatv && aatv != atv) {
int k = aatv->route()->order_key ("editor");
if (k >= okey && k <= key) {
/* in range but don't add it if
it already has tracks selected.
this avoids odd selection
behaviour that feels wrong.
*/
if (find (already_in_selection.begin(),
already_in_selection.end(),
aatv) == already_in_selection.end()) {
relevant_tracks.insert (aatv);
}
}
}
}
}
}
}
}
/* 3. find all selectable objects (regionviews in this case) between that one and the end of the
one that was clicked.
*/
for (set<AudioTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
(*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
}
/* 3. convert to a vector of audio regions */
/* 4. convert to a vector of audio regions */
vector<RegionView*> regions;