modified fix from carl for region copy-moves-original-to-start bug; change verbose...
[ardour.git] / gtk2_ardour / editor_ops.cc
index 6e6d269f21e1c66007745a1c5107d3e497de6a20..f80ec708ebee70178fc003a5c0493ab44989ce7c 100644 (file)
@@ -15,7 +15,6 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
 */
 
 #include <unistd.h>
@@ -32,6 +31,7 @@
 
 #include <gtkmm2ext/utils.h>
 #include <gtkmm2ext/choice.h>
+#include <gtkmm2ext/window_title.h>
 
 #include <ardour/audioengine.h>
 #include <ardour/session.h>
@@ -68,6 +68,7 @@ using namespace ARDOUR;
 using namespace PBD;
 using namespace sigc;
 using namespace Gtk;
+using namespace Gtkmm2ext;
 using namespace Editing;
 
 /***********************************************************************
@@ -1290,332 +1291,6 @@ Editor::add_location_from_audio_region ()
        session->commit_reversible_command ();
 }
 
-void
-Editor::select_all_in_track (Selection::Operation op)
-{
-       list<Selectable *> touched;
-
-       if (!clicked_trackview) {
-               return;
-       }
-       
-       clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
-
-       switch (op) {
-       case Selection::Toggle:
-               selection->add (touched);
-               break;
-       case Selection::Set:
-               selection->set (touched);
-               break;
-       case Selection::Extend:
-               /* not defined yet */
-               break;
-       case Selection::Add:
-               selection->add (touched);
-               break;
-       }
-}
-
-void
-Editor::select_all (Selection::Operation op)
-{
-       list<Selectable *> touched;
-       
-       for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
-               if ((*iter)->hidden()) {
-                       continue;
-               }
-               (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
-       }
-       begin_reversible_command (_("select all"));
-       switch (op) {
-       case Selection::Add:
-       case Selection::Toggle:
-               selection->add (touched);
-               break;
-       case Selection::Set:
-               selection->set (touched);
-               break;
-       case Selection::Extend:
-               /* not defined yet */
-               break;
-       }
-       commit_reversible_command ();
-}
-
-void
-Editor::invert_selection_in_track ()
-{
-       list<Selectable *> touched;
-
-       if (!clicked_trackview) {
-               return;
-       }
-       
-       clicked_trackview->get_inverted_selectables (*selection, touched);
-       selection->set (touched);
-}
-
-void
-Editor::invert_selection ()
-{
-       list<Selectable *> touched;
-       
-       for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
-               if ((*iter)->hidden()) {
-                       continue;
-               }
-               (*iter)->get_inverted_selectables (*selection, touched);
-       }
-
-       selection->set (touched);
-}
-
-bool
-Editor::select_all_within (nframes_t start, nframes_t end, double top, double bot, Selection::Operation op)
-{
-       list<Selectable*> touched;
-       list<Selectable*>::size_type n = 0;
-       TrackViewList touched_tracks;
-
-       for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
-               if ((*iter)->hidden()) {
-                       continue;
-               }
-
-               n = touched.size();
-
-               (*iter)->get_selectables (start, end, top, bot, touched);
-
-               if (n != touched.size()) {
-                       touched_tracks.push_back (*iter);
-               }
-       }
-
-       if (!touched_tracks.empty()) {
-               switch (op) {
-               case Selection::Add:
-                       selection->add (touched_tracks);
-                       break;
-               case Selection::Toggle:
-                       selection->toggle (touched_tracks);
-                       break;
-               case Selection::Set:
-                       selection->set (touched_tracks);
-                       break;
-               case Selection::Extend:
-                       /* not defined yet */
-                       break;
-               }
-       }
-               
-       begin_reversible_command (_("select all within"));
-       switch (op) {
-       case Selection::Add:
-               selection->add (touched);
-               break;
-       case Selection::Toggle:
-               selection->toggle (touched);
-               break;
-       case Selection::Set:
-               selection->set (touched);
-               break;
-       case Selection::Extend:
-               /* not defined yet */
-               break;
-       }
-
-       commit_reversible_command ();
-       return !touched.empty();
-}
-
-void
-Editor::set_selection_from_audio_region ()
-{
-       if (selection->regions.empty()) {
-               return;
-       }
-
-       RegionView* rv = *(selection->regions.begin());
-       boost::shared_ptr<Region> region = rv->region();
-       
-       begin_reversible_command (_("set selection from region"));
-       selection->set (0, region->position(), region->last_frame());
-       commit_reversible_command ();
-
-       set_mouse_mode (Editing::MouseRange, false);
-}
-
-void
-Editor::set_selection_from_punch()
-{
-       Location* location;
-
-       if ((location = session->locations()->auto_punch_location()) == 0)  {
-               return;
-       }
-
-       set_selection_from_range (*location);
-}
-
-void
-Editor::set_selection_from_loop()
-{
-       Location* location;
-
-       if ((location = session->locations()->auto_loop_location()) == 0)  {
-               return;
-       }
-       set_selection_from_range (*location);
-}
-
-void
-Editor::set_selection_from_range (Location& loc)
-{
-       begin_reversible_command (_("set selection from range"));
-       selection->set (0, loc.start(), loc.end());
-       commit_reversible_command ();
-
-       set_mouse_mode (Editing::MouseRange, false);
-}
-
-void
-Editor::select_all_selectables_using_time_selection ()
-{
-       list<Selectable *> touched;
-
-       if (selection->time.empty()) {
-               return;
-       }
-
-       nframes_t start = selection->time[clicked_selection].start;
-       nframes_t end = selection->time[clicked_selection].end;
-
-       if (end - start < 1)  {
-               return;
-       }
-
-       for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
-               if ((*iter)->hidden()) {
-                       continue;
-               }
-               (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
-       }
-
-       begin_reversible_command (_("select all from range"));
-       selection->set (touched);
-       commit_reversible_command ();
-}
-
-
-void
-Editor::select_all_selectables_using_punch()
-{
-       Location* location = session->locations()->auto_punch_location();
-       list<Selectable *> touched;
-
-       if (location == 0 || (location->end() - location->start() <= 1))  {
-               return;
-       }
-
-       for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
-               if ((*iter)->hidden()) {
-                       continue;
-               }
-               (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
-       }
-       begin_reversible_command (_("select all from punch"));
-       selection->set (touched);
-       commit_reversible_command ();
-
-}
-
-void
-Editor::select_all_selectables_using_loop()
-{
-       Location* location = session->locations()->auto_loop_location();
-       list<Selectable *> touched;
-
-       if (location == 0 || (location->end() - location->start() <= 1))  {
-               return;
-       }
-
-       for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
-               if ((*iter)->hidden()) {
-                       continue;
-               }
-               (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
-       }
-       begin_reversible_command (_("select all from loop"));
-       selection->set (touched);
-       commit_reversible_command ();
-
-}
-
-void
-Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
-{
-        nframes_t start;
-       nframes_t end;
-       list<Selectable *> touched;
-
-       if (after) {
-               begin_reversible_command (_("select all after cursor"));
-               start = cursor->current_frame ;
-               end = session->current_end_frame();
-       } else {
-               if (cursor->current_frame > 0) {
-                       begin_reversible_command (_("select all before cursor"));
-                       start = 0;
-                       end = cursor->current_frame - 1;
-               } else {
-                       return;
-               }
-       }
-
-       for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
-               if ((*iter)->hidden()) {
-                       continue;
-               }
-               (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
-       }
-       selection->set (touched);
-       commit_reversible_command ();
-}
-
-void
-Editor::select_all_selectables_between_cursors (Cursor *cursor, Cursor *other_cursor)
-{
-        nframes_t start;
-       nframes_t end;
-       list<Selectable *> touched;
-       bool  other_cursor_is_first = cursor->current_frame > other_cursor->current_frame;
-
-       if (cursor->current_frame == other_cursor->current_frame) {
-               return;
-       }
-
-       begin_reversible_command (_("select all between cursors"));
-       if (other_cursor_is_first) {
-               start = other_cursor->current_frame;
-               end = cursor->current_frame - 1;
-               
-       } else {
-               start = cursor->current_frame;
-               end = other_cursor->current_frame - 1;
-       }
-       
-       for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
-               if ((*iter)->hidden()) {
-                       continue;
-               }
-               (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
-       }
-       selection->set (touched);
-       commit_reversible_command ();
-}
-
 void
 Editor::amplitude_zoom_step (bool in)
 {
@@ -1833,19 +1508,13 @@ Editor::insert_region_list_drag (boost::shared_ptr<AudioRegion> region, int x, i
                return;
        }
        
-       cerr << "drop target playlist, UC  = " << playlist.use_count() << endl;
-
        snap_to (where);
        
        begin_reversible_command (_("insert dragged region"));
         XMLNode &before = playlist->get_state();
-       cerr << "pre add target playlist, UC  = " << playlist.use_count() << endl;
        playlist->add_region (RegionFactory::create (region), where, 1.0);
-       cerr << "post add target playlist, UC  = " << playlist.use_count() << endl;
        session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
        commit_reversible_command ();
-
-       cerr << "post drop target playlist, UC  = " << playlist.use_count() << endl;
 }
 
 void
@@ -1909,6 +1578,30 @@ Editor::edit_envelope ()
 
 /* PLAYBACK */
 
+void
+Editor::transition_to_rolling (bool fwd)
+{
+       if (!session) {
+               return;
+       }
+
+       switch (Config->get_slave_source()) {
+       case None:
+       case JACK:
+               break;
+       default:
+               /* transport controlled by the master */
+               return;
+       }
+
+       if (session->is_auditioning()) {
+               session->cancel_audition ();
+               return;
+       }
+       
+       session->request_transport_speed (fwd ? 1.0f : -1.0f);
+}
+
 void
 Editor::toggle_playback (bool with_abort)
 {
@@ -2066,7 +1759,10 @@ Editor::rename_region ()
                return;
        }
 
-       dialog.set_title (_("ardour: rename region"));
+       WindowTitle title(Glib::get_application_name());
+       title += _("Rename Region");
+
+       dialog.set_title (title.get_string());
        dialog.set_name ("RegionRenameWindow");
        dialog.set_size_request (300, -1);
        dialog.set_position (Gtk::WIN_POS_MOUSE);
@@ -2252,17 +1948,22 @@ Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& n
 void
 Editor::split_multichannel_region ()
 {
-       vector<AudioRegion*> v;
-
-       AudioRegionView* clicked_arv = dynamic_cast<AudioRegionView*>(clicked_regionview);
-       
-       if (!clicked_arv || clicked_arv->audio_region()->n_channels() < 2) {
+       if (selection->regions.empty()) {
                return;
        }
 
-       clicked_arv->audio_region()->separate_by_channel (*session, v);
+       vector<boost::shared_ptr<AudioRegion> > v;
+
+       for (list<RegionView*>::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
+
+               AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*x);
+               
+               if (!arv || arv->audio_region()->n_channels() < 2) {
+                       continue;
+               }
 
-       /* nothing else to do, really */
+               (arv)->audio_region()->separate_by_channel (*session, v);
+       }
 }
 
 void
@@ -2292,6 +1993,12 @@ Editor::separate_region_from_selection ()
                if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
 
                        if (atv->is_audio_track()) {
+
+                               /* no edits to destructive tracks */
+
+                               if (atv->audio_track()->audio_diskstream()->destructive()) {
+                                       continue;
+                               }
                                        
                                if ((playlist = atv->playlist()) != 0) {
                                        if (!doing_undo) {
@@ -2345,6 +2052,12 @@ Editor::separate_regions_using_location (Location& loc)
 
                        if (atv->is_audio_track()) {
                                        
+                               /* no edits to destructive tracks */
+
+                               if (atv->audio_track()->audio_diskstream()->destructive()) {
+                                       continue;
+                               }
+
                                if ((playlist = atv->playlist()) != 0) {
                                         XMLNode *before;
                                        if (!doing_undo) {
@@ -2374,75 +2087,76 @@ Editor::separate_regions_using_location (Location& loc)
 void
 Editor::crop_region_to_selection ()
 {
-       if (selection->time.empty()) {
+       if (selection->time.empty() || selection->tracks.empty()) {
                return;
        }
 
        vector<boost::shared_ptr<Playlist> > playlists;
        boost::shared_ptr<Playlist> playlist;
 
-       if (clicked_trackview != 0) {
-
-               if ((playlist = clicked_trackview->playlist()) == 0) {
-                       return;
-               }
-
-               playlists.push_back (playlist);
-
-       } else {
+       sort_track_selection ();
+       
+       for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
                
-               sort_track_selection ();
-
-               for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
-
-                       AudioTimeAxisView* atv;
+               AudioTimeAxisView* atv;
+               
+               if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
+                       
+                       if (atv->is_audio_track()) {
+                               
+                               /* no edits to destructive tracks */
 
-                       if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
+                               if (atv->audio_track()->audio_diskstream()->destructive()) {
+                                       continue;
+                               }
 
-                               if (atv->is_audio_track()) {
-                                       
-                                       if ((playlist = atv->playlist()) != 0) {
-                                               playlists.push_back (playlist);
-                                       }
+                               if ((playlist = atv->playlist()) != 0) {
+                                       playlists.push_back (playlist);
                                }
                        }
                }
        }
 
-       if (!playlists.empty()) {
-
-               nframes_t start;
-               nframes_t end;
-               nframes_t cnt;
-
-               begin_reversible_command (_("trim to selection"));
-
-               for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
-                       
-                       boost::shared_ptr<Region> region;
-                       
-                       start = selection->time.start();
-
-                       if ((region = (*i)->top_region_at(start)) == 0) {
-                               continue;
-                       }
-                       
-                       /* now adjust lengths to that we do the right thing
-                          if the selection extends beyond the region
-                       */
-                       
-                       start = max (start, region->position());
-                       end = min (selection->time.end_frame(), start + region->length() - 1);
-                       cnt = end - start + 1;
-
-                        XMLNode &before = (*i)->get_state();
-                       region->trim_to (start, cnt, this);
-                        XMLNode &after = (*i)->get_state();
-                       session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
+       if (playlists.empty()) {
+               return;
+       }
+               
+       nframes_t start;
+       nframes_t end;
+       nframes_t cnt;
+       
+       begin_reversible_command (_("trim to selection"));
+       
+       for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
+               
+               boost::shared_ptr<Region> region;
+               
+               start = selection->time.start();
+               
+               if ((region = (*i)->top_region_at(start)) == 0) {
+                       continue;
                }
-
-               commit_reversible_command ();
+               
+               /* now adjust lengths to that we do the right thing
+                  if the selection extends beyond the region
+               */
+               
+               start = max (start, region->position());
+               if (max_frames - start < region->length()) {
+                       end = start + region->length() - 1;
+               } else {
+                       end = max_frames;
+               }
+               end = min (selection->time.end_frame(), end);
+               cnt = end - start + 1;
+               
+               XMLNode &before = (*i)->get_state();
+               region->trim_to (start, cnt, this);
+               XMLNode &after = (*i)->get_state();
+               session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
        }
+       
+       commit_reversible_command ();
 }              
 
 void
@@ -2824,8 +2538,10 @@ Editor::freeze_route ()
        if (interthread_progress_window == 0) {
                build_interthread_progress_window ();
        }
-       
-       interthread_progress_window->set_title (_("ardour: freeze"));
+
+       WindowTitle title(Glib::get_application_name());
+       title += _("Freeze");
+       interthread_progress_window->set_title (title.get_string());
        interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
        interthread_progress_window->show_all ();
        interthread_progress_bar.set_fraction (0.0f);
@@ -2867,15 +2583,15 @@ Editor::bounce_range_selection ()
                return;
        }
 
-       TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
+       TrackSelection views = selection->tracks;
 
        nframes_t start = selection->time[clicked_selection].start;
        nframes_t end = selection->time[clicked_selection].end;
        nframes_t cnt = end - start + 1;
-       
+
        begin_reversible_command (_("bounce range"));
 
-       for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
+       for (TrackViewList::iterator i = views.begin(); i != views.end(); ++i) {
 
                AudioTimeAxisView* atv;
 
@@ -2894,7 +2610,7 @@ Editor::bounce_range_selection ()
                itt.done = false;
                itt.cancel = false;
                itt.progress = false;
-               
+
                 XMLNode &before = playlist->get_state();
                atv->audio_track()->bounce_range (start, cnt, itt);
                 XMLNode &after = playlist->get_state();
@@ -2902,8 +2618,6 @@ Editor::bounce_range_selection ()
        }
        
        commit_reversible_command ();
-       
-       delete views;
 }
 
 void
@@ -3104,19 +2818,22 @@ Editor::cut_copy_regions (CutCopyOp op)
                }
                
                boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
+               boost::shared_ptr<Region> _xx;
                
                switch (op) {
                case Cut:
                        if (!ar) break;
                        
-                       npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
+                       _xx = RegionFactory::create ((*x)->region());
+                       npl->add_region (_xx, (*x)->region()->position() - first_position);
                        pl->remove_region (((*x)->region()));
                        break;
                        
                case Copy:
                        if (!ar) break;
-                       
-                       npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
+
+                       /* copy region before adding, so we're not putting same object into two different playlists */
+                       npl->add_region (RegionFactory::create ((*x)->region()), (*x)->region()->position() - first_position);
                        break;
                        
                case Clear:
@@ -3136,10 +2853,11 @@ Editor::cut_copy_regions (CutCopyOp op)
                foo.push_back ((*i).pl);
        }
        
+
        if (!foo.empty()) {
                cut_buffer->set (foo);
        }
-       
+
        for (set<PlaylistState, lt_playlist>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
                (*pl).playlist->thaw ();
                session->add_command (new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));