first pass at making shift-click to select region extend the selection vertically...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 21 Dec 2007 20:34:55 +0000 (20:34 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 21 Dec 2007 20:34:55 +0000 (20:34 +0000)
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2809 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/ardour-sae-ansi.bindings.in
gtk2_ardour/ardour-sae.menus
gtk2_ardour/ardour.menus
gtk2_ardour/editor.h
gtk2_ardour/editor_actions.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_selection.cc

index 9b27b7f5f0ac694c897c97d111fdc622dc7096ae..523878bd3fe203a64ef83908df5c9267f5ce96bb 100644 (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" "")
index 66d00c51e7dff9fbdf06739f1ac22594f4271c2d..a1818a99658d267d711ee61ac20ce8c6211fd220 100644 (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'/>
index 4681a4451c7f16d112f97161f3ef7dbcca081ee5..a60e52561e3a1831821b8765af13b2b229021eba 100644 (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'/>
index b54555b68d87be5bb21c76f9fbb1297c78b0b09e..8287bde9f1e904e0c03c65b2ee91eb2c511c46be 100644 (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&);
index 320c1cc78190943427a09c35935fce22297c5a92..7e5b4adca3bfbc4c2760e0580458b1b773337c36 100644 (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));
index d5e47c42e31eefb9226a7feaf7e267cb906252ee..b30c44eae036c40fedd1aa4ee9c8975df17f40c0 100644 (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 ()
 {
index 29d7a8a6bb358f806ce5fdaee40892c155703678..1ae304316becacf87a4287ceb2c86aa1ffa83f0e 100644 (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();
-                       }
-                       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();
+                       /* 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 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;
+               } else {
 
-               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;