fixed collision with <SECONDARY>n binding
[ardour.git] / gtk2_ardour / editor.cc
index b7ec7d43b2bed3f24be865413ad6ddc10a1331d1..a66972a7e96d7a52566283c2533469dc4f0721ce 100644 (file)
@@ -80,7 +80,6 @@
 
 #include "control_protocol/control_protocol.h"
 
-#include "actions.h"
 #include "actions.h"
 #include "analysis_window.h"
 #include "audio_clock.h"
@@ -251,6 +250,7 @@ pane_size_watcher (Paned* pane)
 Editor::Editor ()
        : _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
 
+       , _mouse_changed_selection (false)
          /* time display buttons */
        , minsec_label (_("Mins:Secs"))
        , bbt_label (_("Bars:Beats"))
@@ -3191,14 +3191,14 @@ Editor::build_snap_type_menu ()
 void
 Editor::setup_tooltips ()
 {
-       ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
-       ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
-       ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split Regions)"));
-       ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Grab/Select Objects"));
-       ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit Gain/Notes/Automation"));
-       ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
-       ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
-       ARDOUR_UI::instance()->set_tip (mouse_content_button, _("Edit Contents (notes and automation)"));
+       ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Grab mode)"));
+       ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Grab Mode (select/move objects)"));
+       ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split regions)"));
+       ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select time ranges)"));
+       ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
+       ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
+       ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Audition Mode (listen to regions)"));
+       ARDOUR_UI::instance()->set_tip (mouse_content_button, _("Internal Edit Mode (edit notes and gain curves inside regions)"));
        ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
        ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
        ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
@@ -3326,7 +3326,12 @@ Editor::begin_selection_op_history ()
 {
        selection_op_cmd_depth = 0;
        selection_op_history_it = 0;
-       selection_op_history.clear();
+
+       while(!selection_op_history.empty()) {
+               delete selection_op_history.front();
+               selection_op_history.pop_front();
+       }
+
        selection_undo_action->set_sensitive (false);
        selection_redo_action->set_sensitive (false);
        selection_op_history.push_front (&_selection_memento->get_state ());
@@ -3349,20 +3354,31 @@ Editor::commit_reversible_selection_op ()
                if (selection_op_cmd_depth == 1) {
 
                        if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
+                               /**
+                                   The user has undone some selection ops and then made a new one,
+                                   making anything earlier in the list invalid.
+                               */
+                               
                                list<XMLNode *>::iterator it = selection_op_history.begin();
-                               advance (it, selection_op_history_it);
-                               selection_op_history.erase (selection_op_history.begin(), it);
+                               list<XMLNode *>::iterator e_it = it;
+                               advance (e_it, selection_op_history_it);
+                               
+                               for ( ; it != e_it; ++it) {
+                                       delete *it;
+                               }
+                               selection_op_history.erase (selection_op_history.begin(), e_it);
                        }
+
                        selection_op_history.push_front (&_selection_memento->get_state ());
                        selection_op_history_it = 0;
+
+                       selection_undo_action->set_sensitive (true);
+                       selection_redo_action->set_sensitive (false);
                }
 
                if (selection_op_cmd_depth > 0) {
                        selection_op_cmd_depth--;
                }
-
-               selection_undo_action->set_sensitive (true);
-               selection_redo_action->set_sensitive (false);
        }
 }
 
@@ -3378,7 +3394,6 @@ Editor::undo_selection_op ()
                                selection_redo_action->set_sensitive (true);
                        }
                        ++n;
-
                }
                /* is there an earlier entry? */
                if ((selection_op_history_it + 1) >= selection_op_history.size()) {
@@ -3401,7 +3416,6 @@ Editor::redo_selection_op ()
                                selection_undo_action->set_sensitive (true);
                        }
                        ++n;
-
                }
 
                if (selection_op_history_it == 0) {
@@ -3428,12 +3442,25 @@ Editor::begin_reversible_command (GQuark q)
        }
 }
 
+void
+Editor::abort_reversible_command ()
+{
+       if (_session) {
+               while(!before.empty()) {
+                       delete before.front();
+                       before.pop_front();
+               }
+               _session->abort_reversible_command ();
+       }
+}
+
 void
 Editor::commit_reversible_command ()
 {
        if (_session) {
                if (before.size() == 1) {
                        _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
+                       redo_action->set_sensitive(false);
                        undo_action->set_sensitive(true);
                        begin_selection_op_history ();
                }
@@ -3660,7 +3687,7 @@ Editor::build_track_count_menu ()
                visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
                visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
                visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
-               visible_tracks_selector.AddMenuElem (MenuElem (_("Selected"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
                visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
        } else {
                visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
@@ -3672,7 +3699,7 @@ Editor::build_track_count_menu ()
                visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
                visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
                visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
-               visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selected tracks"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
 
                zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
                zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
@@ -4611,7 +4638,7 @@ Editor::sort_track_selection (TrackViewList& sel)
 }
 
 framepos_t
-Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu)
+Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu, bool from_outside_canvas)
 {
        bool ignored;
        framepos_t where = 0;
@@ -4620,8 +4647,10 @@ Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_men
        if(Profile->get_mixbus())
                if (ep == EditAtSelectedMarker)
                        ep=EditAtPlayhead;
-               
-       if (from_context_menu && (ep == EditAtMouse)) {
+
+       if (from_outside_canvas && (ep == EditAtMouse)) {
+               ep = EditAtPlayhead;
+       } else if (from_context_menu && (ep == EditAtMouse)) {
                return  canvas_event_sample (&context_click_event, 0, 0);
        }
 
@@ -4636,7 +4665,13 @@ Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_men
 
        switch (ep) {
        case EditAtPlayhead:
-               where = _session->audible_frame();
+               if (_dragging_playhead) {
+                       if (!mouse_frame (where, ignored)) {
+                               /* XXX not right but what can we do ? */
+                               return 0;
+                       }
+               } else
+                       where = _session->audible_frame();
                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
                break;
 
@@ -4891,17 +4926,17 @@ Editor::get_regions_from_selection_and_entered ()
 }
 
 void
-Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
+Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
 {
        for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
-               RouteTimeAxisView* tatv;
+               RouteTimeAxisView* rtav;
                
-               if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
+               if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
                        boost::shared_ptr<Playlist> pl;
                        std::vector<boost::shared_ptr<Region> > results;
                        boost::shared_ptr<Track> tr;
                        
-                       if ((tr = tatv->track()) == 0) {
+                       if ((tr = rtav->track()) == 0) {
                                /* bus */
                                continue;
                        }
@@ -4909,9 +4944,9 @@ Editor::get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) co
                        if ((pl = (tr->playlist())) != 0) {
                                boost::shared_ptr<Region> r = pl->region_by_id (id);
                                if (r) {
-                                       RegionView* marv = tatv->view()->find_view (r);
-                                       if (marv) {
-                                               regions.push_back (marv);
+                                       RegionView* rv = rtav->view()->find_view (r);
+                                       if (rv) {
+                                               regions.push_back (rv);
                                        }
                                }
                        }
@@ -4919,6 +4954,21 @@ Editor::get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) co
        }
 }
 
+void
+Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
+{
+
+       for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
+               MidiTimeAxisView* mtav;
+
+               if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
+
+                       mtav->get_per_region_note_selection (selection);
+               }
+       }
+       
+}
+
 void
 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
 {
@@ -5094,6 +5144,19 @@ Editor::region_view_added (RegionView * rv)
                        break;
                }
        }
+
+       MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
+       if (mrv) {
+               list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
+               for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
+                       if (rv->region()->id () == (*rnote).first) {
+                               mrv->select_notes ((*rnote).second);
+                               selection->pending_midi_note_selection.erase(rnote);
+                               break;
+                       }
+               }
+       }
+
        _summary->set_background_dirty ();
 }