tracks build ... backends are hard-coded
[ardour.git] / gtk2_ardour / editor_ops.cc
index 116bc4571d28e2d3bd5ec78283c9a6f118cd6c50..2d26a90a86ce5362886b06cff6c1a450dc38860a 100644 (file)
@@ -76,7 +76,7 @@
 #include "editor_regions.h"
 #include "editor_routes.h"
 #include "gui_thread.h"
-#include "insert_time_dialog.h"
+#include "insert_remove_time_dialog.h"
 #include "interthread_progress_window.h"
 #include "item_counts.h"
 #include "keyboard.h"
@@ -2114,6 +2114,54 @@ Editor::add_location_mark (framepos_t where)
        commit_reversible_command ();
 }
 
+void
+Editor::set_session_start_from_playhead ()
+{
+       if (!_session)
+               return;
+       
+       Location* loc;
+       if ((loc = _session->locations()->session_range_location()) == 0) {  //should never happen
+               _session->set_session_extents ( _session->audible_frame(), _session->audible_frame() );
+       } else {
+               XMLNode &before = loc->get_state();
+
+               _session->set_session_extents ( _session->audible_frame(), loc->end() );
+
+               XMLNode &after = loc->get_state();
+
+               begin_reversible_command (_("Set session start"));
+               
+               _session->add_command (new MementoCommand<Location>(*loc, &before, &after));
+
+               commit_reversible_command ();
+       }
+}
+
+void
+Editor::set_session_end_from_playhead ()
+{
+       if (!_session)
+               return;
+       
+       Location* loc;
+       if ((loc = _session->locations()->session_range_location()) == 0) {  //should never happen
+               _session->set_session_extents ( _session->audible_frame(), _session->audible_frame() );
+       } else {
+               XMLNode &before = loc->get_state();
+
+               _session->set_session_extents ( loc->start(), _session->audible_frame() );
+
+               XMLNode &after = loc->get_state();
+
+               begin_reversible_command (_("Set session start"));
+
+               _session->add_command (new MementoCommand<Location>(*loc, &before, &after));
+
+               commit_reversible_command ();
+       }
+}
+
 void
 Editor::add_location_from_playhead_cursor ()
 {
@@ -2435,7 +2483,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 +4581,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
@@ -5134,16 +5182,22 @@ Editor::quantize_regions (const RegionSelection& rs)
                return;
        }
 
-       QuantizeDialog* qd = new QuantizeDialog (*this);
+       if (!quantize_dialog) {
+               quantize_dialog = new QuantizeDialog (*this);
+       }
 
-       qd->present ();
-       const int r = qd->run ();
-       qd->hide ();
+       quantize_dialog->present ();
+       const int r = quantize_dialog->run ();
+       quantize_dialog->hide ();
 
        if (r == Gtk::RESPONSE_OK) {
-               Quantize quant (qd->snap_start(), qd->snap_end(),
-                               qd->start_grid_size(), qd->end_grid_size(),
-                               qd->strength(), qd->swing(), qd->threshold());
+               Quantize quant (quantize_dialog->snap_start(),
+                               quantize_dialog->snap_end(),
+                               quantize_dialog->start_grid_size(),
+                               quantize_dialog->end_grid_size(),
+                               quantize_dialog->strength(),
+                               quantize_dialog->swing(),
+                               quantize_dialog->threshold());
 
                apply_midi_note_edit_op (quant, rs);
        }
@@ -5204,7 +5258,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,8 +6092,6 @@ Editor::set_session_extents_from_selection ()
        if (!get_selection_extents ( start, end))
                return;
 
-       begin_reversible_command (_("set session start/end from selection"));
-
        Location* loc;
        if ((loc = _session->locations()->session_range_location()) == 0) {
                _session->set_session_extents ( start, end );  // this will create a new session range;  no need for UNDO
@@ -6050,6 +6102,8 @@ Editor::set_session_extents_from_selection ()
 
                XMLNode &after = loc->get_state();
 
+               begin_reversible_command (_("set session start/end from selection"));
+
                _session->add_command (new MementoCommand<Location>(*loc, &before, &after));
 
                commit_reversible_command ();
@@ -6878,7 +6932,7 @@ Editor::do_insert_time ()
                return;
        }
 
-       InsertTimeDialog d (*this);
+       InsertRemoveTimeDialog d (*this);
        int response = d.run ();
 
        if (response != RESPONSE_OK) {
@@ -6982,25 +7036,24 @@ Editor::insert_time (
 
                        Locations::LocationList::const_iterator tmp;
 
-                       bool const was_locked = (*i)->locked ();
-                       if (locked_markers_too) {
-                               (*i)->unlock ();
-                       }
-
                        if ((*i)->position_lock_style() == AudioTime || glued_markers_too) {
+                               bool const was_locked = (*i)->locked ();
+                               if (locked_markers_too) {
+                                       (*i)->unlock ();
+                               }
 
                                if ((*i)->start() >= pos) {
-                                       (*i)->set_start ((*i)->start() + frames);
+                                       // move end first, in case we're moving by more than the length of the range
                                        if (!(*i)->is_mark()) {
                                                (*i)->set_end ((*i)->end() + frames);
                                        }
+                                       (*i)->set_start ((*i)->start() + frames);
                                        moved = true;
                                }
 
-                       }
-
-                       if (was_locked) {
-                               (*i)->lock ();
+                               if (was_locked) {
+                                       (*i)->lock ();
+                               }
                        }
                }
 
@@ -7019,6 +7072,167 @@ Editor::insert_time (
        }
 }
 
+void
+Editor::do_remove_time ()
+{
+       if (selection->tracks.empty()) {
+               return;
+       }
+
+       framepos_t pos = get_preferred_edit_position (EDIT_IGNORE_MOUSE);
+       InsertRemoveTimeDialog d (*this, true);
+
+       int response = d.run ();
+
+       if (response != RESPONSE_OK) {
+               return;
+       }
+       
+       framecnt_t distance = d.distance();
+
+       if (distance == 0) {
+               return;
+       }
+
+       remove_time (
+               pos,
+               distance,
+               SplitIntersected,
+               d.move_glued(),
+               d.move_markers(),
+               d.move_glued_markers(),
+               d.move_locked_markers(),
+               d.move_tempos()
+       );
+}
+
+void
+Editor::remove_time (framepos_t pos, framecnt_t frames, InsertTimeOption opt, 
+                    bool ignore_music_glue, bool markers_too, bool glued_markers_too, bool locked_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)->position_lock_style() == AudioTime || glued_markers_too) {
+
+                               bool const was_locked = (*i)->locked ();
+                               if (locked_markers_too) {
+                                       (*i)->unlock ();
+                               }
+
+                               if (!(*i)->is_mark()) {  // it's a 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 {  // only start or end is included, try to do the right thing
+                                               // move start before moving end, to avoid trying to move the end to before the start
+                                               // if we're removing more time than the length of the range
+                                               if ((*i)->start() >= pos && (*i)->start() < pos+frames) {
+                                                       // start is within cut
+                                                       (*i)->set_start (pos);  // bring the start marker to the beginning of the cut
+                                                       moved = true;
+                                               } else if ((*i)->start() >= pos+frames) {
+                                                       // start (and thus entire range) lies beyond end of cut
+                                                       (*i)->set_start ((*i)->start() - frames); // slip the start marker back
+                                                       moved = true;
+                                               }
+                                               if ((*i)->end() >= pos && (*i)->end() < pos+frames) {
+                                                       // end is inside cut
+                                                       (*i)->set_end (pos);  // bring the end to the cut
+                                                       moved = true;
+                                               } else if ((*i)->end() >= pos+frames) {
+                                                       // end is beyond end of cut
+                                                       (*i)->set_end ((*i)->end() - 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;
+                               }
+
+                               if (was_locked) {
+                                       (*i)->lock ();
+                               }
+                       }
+               }
+
+               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().remove_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 ()
 {
@@ -7333,15 +7547,10 @@ Editor::lock ()
                lock_dialog->get_vbox()->show_all ();
                lock_dialog->set_size_request (200, 200);
        }
+
+       delete _main_menu_disabler;
+       _main_menu_disabler = new MainMenuDisabler;
        
-#ifdef __APPLE__
-       /* The global menu bar continues to be accessible to applications
-          with modal dialogs, which means that we need to desensitize
-          all items in the menu bar. Since those items are really just
-          proxies for actions, that means disabling all actions.
-       */
-       ActionManager::disable_all_actions ();
-#endif
        lock_dialog->present ();
 }
 
@@ -7350,9 +7559,7 @@ Editor::unlock ()
 {
        lock_dialog->hide ();
        
-#ifdef __APPLE__
-       ActionManager::pop_action_state ();
-#endif 
+       delete _main_menu_disabler;
 
        if (ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
                start_lock_event_timing ();