Make MIDI tools actually do something. Sorta. Sometimes.
authorDavid Robillard <d@drobilla.net>
Thu, 9 Aug 2007 20:50:56 +0000 (20:50 +0000)
committerDavid Robillard <d@drobilla.net>
Thu, 9 Aug 2007 20:50:56 +0000 (20:50 +0000)
When the moon is right.
Cosmic radiation may be a factor.
Prayer may not be an entirely bad idea, just in case.

git-svn-id: svn://localhost/ardour2/trunk@2283 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/canvas-midi-event.cc
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_mouse.cc
gtk2_ardour/midi_region_view.cc
gtk2_ardour/midi_region_view.h

index 1e8e313684e4412501879fadc911ed227efd3f4e..625d16ffd5c103dddb32daba4fc0b70cdea1ffd1 100644 (file)
@@ -73,7 +73,9 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
 
        switch (ev->type) {
        case GDK_KEY_PRESS:
+               cerr << "EV KEY\n";
                if (_note && ev->key.keyval == GDK_Delete) {
+                       cerr << "EV DELETE KEY\n";
                        selected(true);
                        _region.start_remove_command();
                        _region.command_remove_note(this);
@@ -92,8 +94,8 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
                if (select_mod) {
                        _region.note_selected(this, true);
                }
-               Keyboard::magic_widget_grab_focus();
                _item->grab_focus();
+               Keyboard::magic_widget_grab_focus();
                _region.note_entered(this);
                break;
 
@@ -123,6 +125,7 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
                                last_y = event_y;
                                drag_delta_x = 0;
                                drag_delta_note = 0;
+                               _region.note_selected(this, true);
                        }
                        return true;
 
@@ -178,14 +181,20 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
 
                switch (_state) {
                case Pressed: // Clicked
-                       _state = None;
-                       
-                       if (_selected && !select_mod && _region.selection_size() > 1)
-                               _region.unique_select(this);
-                       else if (_selected)
-                               _region.note_deselected(this, select_mod);
-                       else
-                               _region.note_selected(this, select_mod);
+                       if (_region.midi_view()->editor.current_midi_edit_mode() == Editing::MidiEditSelect) {
+                               _state = None;
+
+                               if (_selected && !select_mod && _region.selection_size() > 1)
+                                       _region.unique_select(this);
+                               else if (_selected)
+                                       _region.note_deselected(this, select_mod);
+                               else
+                                       _region.note_selected(this, select_mod);
+                       } else if (_region.midi_view()->editor.current_midi_edit_mode() == Editing::MidiEditErase) {
+                               _region.start_remove_command();
+                               _region.command_remove_note(this);
+                               _region.apply_command();
+                       }
 
                        return true;
                case Dragging: // Dropped
index 952e5b098a06db7413907a61316754ce1e472626..bc9e38418a964072554ca42f8971498626b23d36 100644 (file)
@@ -301,6 +301,7 @@ Editor::Editor ()
        temp_location = 0;
        leftmost_frame = 0;
        ignore_mouse_mode_toggle = false;
+       ignore_midi_edit_mode_toggle = false;
        current_stepping_trackview = 0;
        entered_track = 0;
        entered_regionview = 0;
@@ -326,6 +327,7 @@ Editor::Editor ()
        marker_drag_line = 0;
        
        set_mouse_mode (MouseObject, true);
+       set_midi_edit_mode (MidiEditSelect, true);
 
        frames_per_unit = 2048; /* too early to use reset_zoom () */
        reset_hscrollbar_stepping ();
@@ -2621,6 +2623,12 @@ Editor::setup_midi_toolbar ()
        midi_tool_pencil_button.unset_flags (CAN_FOCUS);
        midi_tool_erase_button.unset_flags (CAN_FOCUS);
        
+       midi_tool_select_button.signal_toggled().connect (bind (mem_fun(*this,
+                               &Editor::midi_edit_mode_toggled), Editing::MidiEditSelect));
+       midi_tool_pencil_button.signal_toggled().connect (bind (mem_fun(*this,
+                               &Editor::midi_edit_mode_toggled), Editing::MidiEditPencil));
+       midi_tool_erase_button.signal_toggled().connect (bind (mem_fun(*this,
+                               &Editor::midi_edit_mode_toggled), Editing::MidiEditErase));
        
        /* Pack everything in... */
 
index cae4da5a044e86b9aec470754d465f3b23b4af90..685d56db70614f61ffa68edec15c181be64f1437 100644 (file)
@@ -1388,8 +1388,8 @@ class Editor : public PublicEditor
        Gtk::ToggleButton        midi_tool_pencil_button;
        Gtk::ToggleButton        midi_tool_erase_button;
        GroupedButtons          *midi_tool_button_set;
-       //void                     midi_tool_toggled (Editing::MouseMode m);
-       //bool                     ignore_midi_tool_toggle;
+       void                     midi_edit_mode_toggled (Editing::MidiEditMode m);
+       bool                     ignore_midi_edit_mode_toggle;
 
        Gtkmm2ext::TearOff* midi_tools_tearoff;
        Gtk::HBox           midi_toolbar_hbox;
index 0423e1aab396e9a17ec51ccac4d4c5bfb8b5ae05..4ba1213d6279783a776f6a5426188b75ffb9f295 100644 (file)
@@ -310,6 +310,38 @@ Editor::step_mouse_mode (bool next)
        }
 }
 
+void
+Editor::midi_edit_mode_toggled (MidiEditMode m)
+{
+       if (ignore_midi_edit_mode_toggle) {
+               return;
+       }
+
+       switch (m) {
+       case MidiEditSelect:
+               if (midi_tool_select_button.get_active()) {
+                       set_midi_edit_mode (m);
+               }
+               break;
+       
+       case MidiEditPencil:
+               if (midi_tool_pencil_button.get_active()) {
+                       set_midi_edit_mode (m);
+               }
+               break;
+       
+       case MidiEditErase:
+               if (midi_tool_erase_button.get_active()) {
+                       set_midi_edit_mode (m);
+               }
+               break;
+
+       default:
+               break;
+       }
+}      
+
+
 void
 Editor::set_midi_edit_mode (MidiEditMode m, bool force)
 {
@@ -325,7 +357,7 @@ Editor::set_midi_edit_mode (MidiEditMode m, bool force)
 
        instant_save ();
        
-       //ignore_midi_edit_mode_toggle = true;
+       ignore_midi_edit_mode_toggle = true;
 
        switch (midi_edit_mode) {
        case MidiEditSelect:
@@ -349,7 +381,7 @@ Editor::set_midi_edit_mode (MidiEditMode m, bool force)
        else
                midi_toolbar_frame.hide();
 
-       //ignore_midi_edit_mode_toggle = false;
+       ignore_midi_edit_mode_toggle = false;
 
        /*if (is_drawable()) {
                track_canvas.get_window()->set_cursor(*current_canvas_cursor);
index 8e9008769729d2fd9ad2f9523d7cfdd4f0078ab6..c58a92e9b7871e603850dc119fd4959c26a1732a 100644 (file)
@@ -63,9 +63,12 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &
        : RegionView (parent, tv, r, spu, basic_color)
        , _default_note_length(0.0)
        , _active_notes(0)
+       , _note_group(new ArdourCanvas::Group(*parent))
        , _delta_command(NULL)
-       , _command_mode(None)
+       , _mouse_state(None)
+       , _pressed_button(0)
 {
+       _note_group->raise_to_top();
 }
 
 MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr<MidiRegion> r, double spu, 
@@ -73,9 +76,12 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &
        : RegionView (parent, tv, r, spu, basic_color, visibility)
        , _default_note_length(0.0)
        , _active_notes(0)
+       , _note_group(new ArdourCanvas::Group(*parent))
        , _delta_command(NULL)
-       , _command_mode(None)
+       , _mouse_state(None)
+       , _pressed_button(0)
 {
+       _note_group->raise_to_top();
 }
 
 void
@@ -124,39 +130,49 @@ MidiRegionView::init (Gdk::Color& basic_color, bool wfd)
 bool
 MidiRegionView::canvas_event(GdkEvent* ev)
 {
-       enum State { None, Pressed, SelectDragging, AddDragging };
-       static int press_button = 0;
-       static State _state;
+       static bool delete_mod = false;
+       static Editing::MidiEditMode original_mode;
 
        static double drag_start_x, drag_start_y;
        static double last_x, last_y;
        double event_x, event_y;
+       nframes_t event_frame = 0;
 
        static ArdourCanvas::SimpleRect* drag_rect = NULL;
        
        if (trackview.editor.current_mouse_mode() != MouseNote)
                return false;
 
+       // Mmmm, spaghetti
+       
        switch (ev->type) {
        case GDK_KEY_PRESS:
-               if (ev->key.keyval == GDK_Delete) {
+               if (ev->key.keyval == GDK_Delete && !delete_mod) {
+                       delete_mod = true;
+                       original_mode = trackview.editor.current_midi_edit_mode();
                        trackview.editor.set_midi_edit_mode(MidiEditErase);
                        start_remove_command();
+                       _mouse_state = EraseDragging;
                }
                break;
        
        case GDK_KEY_RELEASE:
-               if (_command_mode == Remove && ev->key.keyval == GDK_Delete) {
-                       delete_selection();
-                       apply_command();
-                       trackview.editor.set_midi_edit_mode(MidiEditSelect);
+               if (ev->key.keyval == GDK_Delete) {
+                       if (_mouse_state == EraseDragging) {
+                               delete_selection();
+                               apply_command();
+                       }
+                       if (delete_mod) {
+                               trackview.editor.set_midi_edit_mode(original_mode);
+                               delete_mod = false;
+                       }
                }
                break;
 
        case GDK_BUTTON_PRESS:
                //group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, ev->button.time);
-               _state = Pressed;
-               press_button = ev->button.button;
+               _mouse_state = Pressed;
+               _pressed_button = ev->button.button;
                //cerr << "PRESSED: " << press_button << endl;
                return true;
        
@@ -170,11 +186,16 @@ MidiRegionView::canvas_event(GdkEvent* ev)
                event_x = ev->motion.x;
                event_y = ev->motion.y;
                group->w2i(event_x, event_y);
+                               
+               event_frame = trackview.editor.pixel_to_frame(event_x);
+               trackview.editor.snap_to(event_frame);
 
-               switch (_state) {
+               switch (_mouse_state) {
                case Pressed: // Drag start
 
-                       if (press_button == 1 && _command_mode != Remove) { // Select rect start
+                       // Select rect start
+                       if (_pressed_button == 1 && trackview.editor.current_midi_edit_mode() == MidiEditSelect) {
+                               cerr << "SELECT START\n";
                                group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
                                                Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
                                last_x = event_x;
@@ -193,22 +214,21 @@ MidiRegionView::canvas_event(GdkEvent* ev)
                                drag_rect->property_fill_color_rgba()
                                        = ARDOUR_UI::config()->canvasvar_MidiSelectRectFill.get();
 
-                               _state = SelectDragging;
+                               _mouse_state = SelectDragging;
                                return true;
 
-                       } else if (press_button == 3) { // Add note drag start
+                       // Add note drag start
+                       } else if (trackview.editor.current_midi_edit_mode() == MidiEditPencil) {
+                               cerr << "PENCIL START\n";
                                group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
                                                Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
                                last_x = event_x;
                                last_y = event_y;
                                drag_start_x = event_x;
                                drag_start_y = event_y;
-                               
-                               nframes_t event_frame = midi_view()->editor.pixel_to_frame(event_x);
-                               midi_view()->editor.snap_to(event_frame);
 
                                drag_rect = new ArdourCanvas::SimpleRect(*group);
-                               drag_rect->property_x1() = midi_view()->editor.frame_to_pixel(event_frame);
+                               drag_rect->property_x1() = trackview.editor.frame_to_pixel(event_frame);
                                
                                drag_rect->property_y1() = midi_stream_view()->note_to_y(midi_stream_view()->y_to_note(event_y));
                                drag_rect->property_x2() = event_x;
@@ -218,8 +238,14 @@ MidiRegionView::canvas_event(GdkEvent* ev)
 
                                drag_rect->property_fill_color_rgba() = 0xFFFFFF66;
 
-                               _state = AddDragging;
+                               _mouse_state = AddDragging;
                                return true;
+
+                       // Eraser drag start
+                       } else if (trackview.editor.current_midi_edit_mode() == MidiEditErase) {
+                               cerr << "ERASE DRAGGING\n";
+                               _mouse_state = EraseDragging;
+                               return false; // ?
                        }
 
                        break;
@@ -235,16 +261,13 @@ MidiRegionView::canvas_event(GdkEvent* ev)
                                event_y = t_y;
                        }
 
-                       if (_state == AddDragging) {
-                               nframes_t event_frame = midi_view()->editor.pixel_to_frame(event_x);
-                               midi_view()->editor.snap_to(event_frame);
-                               event_x = midi_view()->editor.frame_to_pixel(event_frame);
-                       }
+                       if (_mouse_state == AddDragging)
+                               event_x = trackview.editor.frame_to_pixel(event_frame);
 
                        if (drag_rect)
                                drag_rect->property_x2() = event_x;
 
-                       if (drag_rect && _state == SelectDragging) {
+                       if (drag_rect && _mouse_state == SelectDragging) {
                                drag_rect->property_y2() = event_y;
 
                                update_drag_selection(drag_start_x, event_x, drag_start_y, event_y);
@@ -253,9 +276,11 @@ MidiRegionView::canvas_event(GdkEvent* ev)
                        last_x = event_x;
                        last_y = event_y;
 
+               case EraseDragging:
                        return true;
+
                default:
-                       _state = None;
+                       _mouse_state = None;
                        break;
                }
                break;
@@ -265,25 +290,30 @@ MidiRegionView::canvas_event(GdkEvent* ev)
                event_y = ev->motion.y;
                group->w2i(event_x, event_y);
                group->ungrab(ev->button.time);
-               switch (_state) {
+               event_frame = trackview.editor.pixel_to_frame(event_x);
+
+               switch (_mouse_state) {
                case Pressed: // Clicked
-                       if (ev->button.button == 1) {
+                       switch (trackview.editor.current_midi_edit_mode()) {
+                       case MidiEditSelect:
                                clear_selection();
-                       } else if (ev->button.button == 3) {
-                               nframes_t event_frame = midi_view()->editor.pixel_to_frame(event_x);
-                               midi_view()->editor.snap_to(event_frame);
-                               event_x = midi_view()->editor.frame_to_pixel(event_frame);
+                               break;
+                       case MidiEditPencil:
+                               trackview.editor.snap_to(event_frame);
+                               event_x = trackview.editor.frame_to_pixel(event_frame);
                                create_note_at(event_x, event_y, _default_note_length);
+                       default:
+                               break;
                        }
-                       _state = None;
+                       _mouse_state = None;
                        return true;
                case SelectDragging: // Select drag done
-                       _state = None;
+                       _mouse_state = None;
                        delete drag_rect;
                        drag_rect = NULL;
                        return true;
                case AddDragging: // Add drag done
-                       _state = None;
+                       _mouse_state = None;
                        if (drag_rect->property_x2() > drag_rect->property_x1() + 2) {
                                create_note_at(drag_rect->property_x1(), drag_rect->property_y1(),
                                                trackview.editor.pixel_to_frame(
@@ -483,7 +513,8 @@ MidiRegionView::add_event (const MidiEvent& ev)
        }
        printf("\n\n");*/
 
-       ArdourCanvas::Group* const group = (ArdourCanvas::Group*)get_canvas_group();
+       //ArdourCanvas::Group* const group = (ArdourCanvas::Group*)get_canvas_group();
+       ArdourCanvas::Group* const group = _note_group;
        
        if (midi_view()->note_mode() == Sustained) {
                if ((ev.buffer()[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
@@ -666,6 +697,7 @@ MidiRegionView::update_drag_selection(double last_x, double x, double last_y, do
 void
 MidiRegionView::move_selection(double dx, double dy)
 {
+       cerr << "MOVE SELECTION: " << dx << ", " << dy << endl;
        for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i)
                (*i)->item()->move(dx, dy);
 }
index 38d61703fa8eb3ef09da5a1bbe793d92d7ee1f76..fb3e4d344954275a1eaacc279ca506e93ec2085a 100644 (file)
@@ -89,13 +89,11 @@ class MidiRegionView : public RegionView
        /* This stuff is a bit boilerplatey ATM.  Work in progress. */
 
        inline void start_remove_command() {
-               _command_mode = Remove;
                if (!_delta_command)
                        _delta_command = _model->new_delta_command();
        }
        
        inline void start_delta_command() {
-               _command_mode = Delta;
                if (!_delta_command)
                        _delta_command = _model->new_delta_command();
        }
@@ -114,7 +112,9 @@ class MidiRegionView : public RegionView
        }
 
        void note_entered(ArdourCanvas::CanvasMidiEvent* ev) {
-               if (_command_mode == Remove && _delta_command && ev->note()) {
+               cerr << "ENTERED, STATE = " << _mouse_state << endl;
+               if (_mouse_state == EraseDragging) {
+                       start_delta_command();
                        ev->selected(true);
                        _delta_command->remove(*ev->note());
                }
@@ -123,7 +123,6 @@ class MidiRegionView : public RegionView
        void abort_command() {
                delete _delta_command;
                _delta_command = NULL;
-               _command_mode = None;
                clear_selection();
        }
 
@@ -132,7 +131,6 @@ class MidiRegionView : public RegionView
                        _model->apply_command(_delta_command);
                        _delta_command = NULL;
                }
-               _command_mode = None;
                midi_view()->midi_track()->diskstream()->playlist_modified();
        }
 
@@ -182,13 +180,15 @@ class MidiRegionView : public RegionView
        boost::shared_ptr<ARDOUR::MidiModel>        _model;
        std::vector<ArdourCanvas::CanvasMidiEvent*> _events;
        ArdourCanvas::CanvasNote**                  _active_notes;
+       ArdourCanvas::Group*                        _note_group;
        ARDOUR::MidiModel::DeltaCommand*            _delta_command;
+       
+       enum MouseState { None, Pressed, SelectDragging, AddDragging, EraseDragging };
+       MouseState _mouse_state;
+       int _pressed_button;
 
        typedef std::set<ArdourCanvas::CanvasMidiEvent*> Selection;
        Selection _selection;
-       
-       enum CommandMode { None, Remove, Delta };
-       CommandMode _command_mode;
 };
 
 #endif /* __gtk_ardour_midi_region_view_h__ */