update windows installer finish page text & link
[ardour.git] / gtk2_ardour / editor_ops.cc
index a4509e2e1e6f54c3cb732401e546acfad0f8788b..0cef0d90e5d3a8ccc95aa6801dfa4c84a278f71c 100644 (file)
@@ -2435,7 +2435,7 @@ Editor::play_from_edit_point_and_return ()
        framepos_t start_frame;
        framepos_t return_frame;
 
-       start_frame = get_preferred_edit_position (true);
+       start_frame = get_preferred_edit_position ( EDIT_IGNORE_PHEAD );
 
        if (_session->transport_rolling()) {
                _session->request_locate (start_frame, false);
@@ -4533,7 +4533,7 @@ Editor::paste (float times, bool from_context)
 {
         DEBUG_TRACE (DEBUG::CutNPaste, "paste to preferred edit pos\n");
 
-       paste_internal (get_preferred_edit_position (false, from_context), times);
+       paste_internal (get_preferred_edit_position (EDIT_IGNORE_NONE, from_context), times);
 }
 
 void
@@ -5204,7 +5204,7 @@ Editor::insert_patch_change (bool from_context)
                return;
        }
 
-       const framepos_t p = get_preferred_edit_position (false, from_context);
+       const framepos_t p = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context);
 
        /* XXX: bit of a hack; use the MIDNAM from the first selected region;
           there may be more than one, but the PatchChangeDialog can only offer
@@ -6038,7 +6038,7 @@ Editor::set_session_extents_from_selection ()
        if (!get_selection_extents ( start, end))
                return;
 
-       begin_reversible_command (_("set session start/stop from selection"));
+       begin_reversible_command (_("set session start/end from selection"));
 
        Location* loc;
        if ((loc = _session->locations()->session_range_location()) == 0) {
@@ -6749,6 +6749,23 @@ Editor::toggle_tracks_active ()
 
 void
 Editor::remove_tracks ()
+{
+       /* this will delete GUI objects that may be the subject of an event
+          handler in which this method is called. Defer actual deletion to the
+          next idle callback, when all event handling is finished.
+       */
+       Glib::signal_idle().connect (sigc::mem_fun (*this, &Editor::idle_remove_tracks));
+}
+
+bool
+Editor::idle_remove_tracks ()
+{
+       _remove_tracks ();
+       return false; /* do not call again */
+}
+
+void
+Editor::_remove_tracks ()
 {
        TrackSelection& ts (selection->tracks);
 
@@ -6804,19 +6821,9 @@ edit your ardour.rc file to set the\n\
                return;
        }
 
-       // XXX should be using gettext plural forms, maybe?
-       if (ntracks > 1) {
-               trackstr = _("tracks");
-       } else {
-               trackstr = _("track");
-       }
-
-       if (nbusses > 1) {
-               busstr = _("busses");
-       } else {
-               busstr = _("bus");
-       }
-
+       trackstr = P_("track", "tracks", ntracks);
+       busstr = P_("bus", "busses", nbusses);
+       
        if (ntracks) {
                if (nbusses) {
                        prompt  = string_compose (_("Do you really want to remove %1 %2 and %3 %4?\n"
@@ -7011,6 +7018,175 @@ Editor::insert_time (
                commit_reversible_command ();
        }
 }
+void
+Editor::do_cut_time ()
+{
+       if (selection->tracks.empty()) {
+               return;
+       }
+
+       framepos_t pos = get_preferred_edit_position (EDIT_IGNORE_MOUSE);
+       ArdourDialog d (*this, _("Cut Time"));
+       VButtonBox button_box;
+       VBox option_box;
+
+       CheckButton glue_button (_("Move Glued Regions"));  glue_button.set_active();
+       CheckButton marker_button (_("Move Markers"));  marker_button.set_active();
+       CheckButton tempo_button (_("Move Tempo & Meters"));  tempo_button.set_active();
+       AudioClock clock ("cutTimeClock", true, "", true, false, true, false);
+       HBox clock_box;
+
+       clock.set (0);
+       clock.set_session (_session);
+       clock.set_bbt_reference (pos);
+
+       clock_box.pack_start (clock, false, true);
+
+       option_box.set_spacing (6);
+       option_box.pack_start (button_box, false, false);
+       option_box.pack_start (glue_button, false, false);
+       option_box.pack_start (marker_button, false, false);
+       option_box.pack_start (tempo_button, false, false);
+
+       d.get_vbox()->set_border_width (12);
+       d.get_vbox()->pack_start (clock_box, false, false);
+       d.get_vbox()->pack_start (option_box, false, false);
+       
+       option_box.show ();
+       button_box.show ();
+       glue_button.show ();
+       clock.show_all();
+       clock_box.show ();
+       marker_button.show ();
+       tempo_button.show ();
+
+       d.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+       d.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
+       d.show ();
+
+       int response = d.run ();
+
+       if (response != RESPONSE_OK) {
+               return;
+       }
+       
+       framecnt_t distance = clock.current_duration (pos);
+
+       if (distance == 0) {
+               return;
+       }
+
+       cut_time (pos, distance, SplitIntersected, glue_button.get_active(), marker_button.get_active(), tempo_button.get_active());
+}
+
+void
+Editor::cut_time (framepos_t pos, framecnt_t frames, InsertTimeOption opt, 
+                    bool ignore_music_glue, bool markers_too, bool tempo_too)
+{
+       bool commit = false;
+       
+       if (Config->get_edit_mode() == Lock) {
+               error << (_("Cannot insert or delete time when in Lock edit.")) << endmsg;
+               return;
+       }
+
+       begin_reversible_command (_("cut time"));
+
+       for (TrackSelection::iterator x = selection->tracks.begin(); x != selection->tracks.end(); ++x) {
+               /* regions */
+               boost::shared_ptr<Playlist> pl = (*x)->playlist();
+               
+               if (pl) {
+
+                       XMLNode &before = pl->get_state();
+                       
+                       std::list<AudioRange> rl;
+                       AudioRange ar(pos, pos+frames, 0);
+                       rl.push_back(ar);
+                       pl->cut (rl);
+                       pl->shift (pos, -frames, true, ignore_music_glue);
+                       
+                       XMLNode &after = pl->get_state();
+                       
+                       _session->add_command (new MementoCommand<Playlist> (*pl, &before, &after));
+                       commit = true;
+               }
+                       
+               /* automation */
+               RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (*x);
+               if (rtav) {
+                       rtav->route ()->shift (pos, -frames);
+                       commit = true;
+               }
+       }
+
+       std::list<Location*> loc_kill_list;
+       
+       /* markers */
+       if (markers_too) {
+               bool moved = false;
+               XMLNode& before (_session->locations()->get_state());
+               Locations::LocationList copy (_session->locations()->list());
+
+               for (Locations::LocationList::iterator i = copy.begin(); i != copy.end(); ++i) {
+                       
+                       if (!(*i)->is_mark()) {  //range;  have to handle both start and end
+                                       if ((*i)->end() >= pos
+                                       && (*i)->end() < pos+frames
+                                       && (*i)->start() >= pos
+                                       && (*i)->end() < pos+frames) {  //range is completely enclosed;  kill it
+                                               moved = true;
+                                               loc_kill_list.push_back(*i);
+                                       } else {  //ony start or end is included, try to do the right thing
+                                               if ((*i)->end() >= pos && (*i)->end() < pos+frames) {
+                                                       (*i)->set_end (pos);  //bring the end to the cut
+                                                       moved = true;
+                                               } else if ((*i)->end() >= pos) {
+                                                       (*i)->set_end ((*i)->end()-frames); //slip the end marker back
+                                                       moved = true;
+                                               }
+                                               if ((*i)->start() >= pos && (*i)->start() < pos+frames) {
+                                                       (*i)->set_start (pos);  //bring the start marker to the beginning of the cut
+                                                       moved = true;
+                                               } else if ((*i)->start() >= pos) {
+                                                       (*i)->set_start ((*i)->start() -frames); //slip the end marker back
+                                                       moved = true;
+                                               }
+                                       }
+                       } else if ((*i)->start() >= pos && (*i)->start() < pos+frames ) {
+                               loc_kill_list.push_back(*i);
+                               moved = true;
+                       } else if ((*i)->start() >= pos) {
+                               (*i)->set_start ((*i)->start() -frames);
+                               moved = true;
+                       }
+               }
+
+               for (list<Location*>::iterator i = loc_kill_list.begin(); i != loc_kill_list.end(); ++i) {
+                       _session->locations()->remove( *i );
+               }
+       
+               if (moved) {
+                       XMLNode& after (_session->locations()->get_state());
+                       _session->add_command (new MementoCommand<Locations>(*_session->locations(), &before, &after));
+                       commit = true;
+               }
+       }
+       
+       if (tempo_too) {
+               XMLNode& before (_session->tempo_map().get_state());
+
+               if (_session->tempo_map().cut_time (pos, frames) ) {
+                       XMLNode& after (_session->tempo_map().get_state());
+                       _session->add_command (new MementoCommand<TempoMap>(_session->tempo_map(), &before, &after));
+                       commit = true;
+               }
+       }
+       
+       if (commit) {
+               commit_reversible_command ();
+       }
+}
 
 void
 Editor::fit_selection ()