changes to help strp silence
[ardour.git] / gtk2_ardour / midi_region_view.cc
index 8d186eac9bf9088da60e2ccb443e120166147926..aec77df8c08a35146a47cc15023ab75177d444ea 100644 (file)
@@ -29,6 +29,7 @@
 #include <sigc++/signal.h>
 
 #include "pbd/memento_command.h"
+#include "pbd/stateful_diff_command.h"
 
 #include "ardour/playlist.h"
 #include "ardour/tempo.h"
@@ -89,6 +90,8 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &
        , _pressed_button(0)
        , _sort_needed (true)
        , _optimization_iterator (_events.end())
+       , _list_editor (0)
+       , no_sound_notes (false)
 {
        _note_group->raise_to_top();
 }
@@ -110,6 +113,8 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &
        , _pressed_button(0)
        , _sort_needed (true)
        , _optimization_iterator (_events.end())
+       , _list_editor (0)
+       , no_sound_notes (false)
 
 {
        _note_group->raise_to_top();
@@ -132,6 +137,8 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other)
        , _pressed_button(0)
        , _sort_needed (true)
        , _optimization_iterator (_events.end())
+       , _list_editor (0)
+       , no_sound_notes (false)
 {
        Gdk::Color c;
        int r,g,b,a;
@@ -157,6 +164,8 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr<M
        , _pressed_button(0)
        , _sort_needed (true)
        , _optimization_iterator (_events.end())
+       , _list_editor (0)
+       , no_sound_notes (false)
 {
        Gdk::Color c;
        int r,g,b,a;
@@ -185,7 +194,7 @@ MidiRegionView::init (Gdk::Color const & basic_color, bool wfd)
 
        region_muted ();
        region_sync_changed ();
-       region_resized (BoundsChanged);
+       region_resized (ARDOUR::bounds_change);
        region_locked ();
 
        reset_width_dependent_items (_pixel_width);
@@ -517,8 +526,10 @@ MidiRegionView::canvas_event(GdkEvent* ev)
 void
 MidiRegionView::show_list_editor ()
 {
-       MidiListEditor* mle = new MidiListEditor (trackview.session(), midi_region());
-       mle->show ();
+       if (!_list_editor) {
+               _list_editor = new MidiListEditor (trackview.session(), midi_region());
+       }
+       _list_editor->present ();
 }
 
 /** Add a note to the model, and the view, at a canvas (click) coordinate.
@@ -938,6 +949,8 @@ MidiRegionView::~MidiRegionView ()
 {
        in_destructor = true;
 
+       delete _list_editor;
+
        RegionViewGoingAway (this); /* EMIT_SIGNAL */
 
        if (_active_notes) {
@@ -951,11 +964,11 @@ MidiRegionView::~MidiRegionView ()
 }
 
 void
-MidiRegionView::region_resized (Change what_changed)
+MidiRegionView::region_resized (const PropertyChange& what_changed)
 {
        RegionView::region_resized(what_changed);
 
-       if (what_changed & ARDOUR::PositionChanged) {
+       if (what_changed.contains (ARDOUR::Properties::position)) {
                set_duration(_region->length(), 0);
                if (_enable_display) {
                        redisplay_model();
@@ -1071,7 +1084,7 @@ MidiRegionView::add_ghost (TimeAxisView& tv)
                }
        }
 
-       ghost->GoingAway.connect (*this, ui_bind (&RegionView::remove_ghost, this, _1), gui_context());
+       GhostRegion::CatchDeletion.connect (*this, ui_bind (&RegionView::remove_ghost, this, _1), gui_context());
 
        return ghost;
 }
@@ -1139,7 +1152,7 @@ MidiRegionView::extend_active_notes()
 void
 MidiRegionView::play_midi_note(boost::shared_ptr<NoteType> note)
 {
-       if (!trackview.editor().sound_notes()) {
+       if (no_sound_notes || !trackview.editor().sound_notes()) {
                return;
        }
 
@@ -1522,6 +1535,91 @@ MidiRegionView::unique_select(ArdourCanvas::CanvasNoteEvent* ev)
        }
 }
 
+void
+MidiRegionView::select_matching_notes (uint8_t notenum, uint16_t channel_mask, bool add, bool extend)
+{
+       uint8_t low_note = 127;
+       uint8_t high_note = 0;
+       MidiModel::Notes& notes (_model->notes());
+       _optimization_iterator = _events.begin();
+
+       if (extend && _selection.empty()) {
+               extend = false;
+       }
+
+       if (extend) {
+
+               /* scan existing selection to get note range */
+
+               for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
+                       if ((*i)->note()->note() < low_note) {
+                               low_note = (*i)->note()->note();
+                       }
+                       if ((*i)->note()->note() > high_note) {
+                               high_note = (*i)->note()->note();
+                       }
+               }
+
+               low_note = min (low_note, notenum);
+               high_note = max (high_note, notenum);
+       }
+
+       no_sound_notes = true;
+
+       for (MidiModel::Notes::iterator n = notes.begin(); n != notes.end(); ++n) {
+
+               boost::shared_ptr<NoteType> note (*n);
+               CanvasNoteEvent* cne;
+               bool select = false;
+
+               if (((0x0001 << note->channel()) & channel_mask) != 0) {
+                       if (extend) {
+                               if ((note->note() >= low_note && note->note() <= high_note)) {
+                                       select = true;
+                               }
+                       } else if (note->note() == notenum) {
+                               select = true;
+                       }
+               }
+
+               if (select) {
+                       if ((cne = find_canvas_note (note)) != 0) {
+                               // extend is false because we've taken care of it, 
+                               // since it extends by time range, not pitch.
+                               note_selected (cne, add, false);
+                       }
+               }
+               
+               add = true; // we need to add all remaining matching notes, even if the passed in value was false (for "set")
+
+       }
+
+       no_sound_notes = false;
+}
+
+void
+MidiRegionView::toggle_matching_notes (uint8_t notenum, uint16_t channel_mask)
+{
+       MidiModel::Notes& notes (_model->notes());
+       _optimization_iterator = _events.begin();
+
+       for (MidiModel::Notes::iterator n = notes.begin(); n != notes.end(); ++n) {
+
+               boost::shared_ptr<NoteType> note (*n);
+               CanvasNoteEvent* cne;
+
+               if (note->note() == notenum && (((0x0001 << note->channel()) & channel_mask) != 0)) {
+                       if ((cne = find_canvas_note (note)) != 0) {
+                               if (cne->selected()) {
+                                       note_deselected (cne);
+                               } else {
+                                       note_selected (cne, true, false);
+                               }
+                       }
+               }
+       }
+}
+
 void
 MidiRegionView::note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add, bool extend)
 {
@@ -2433,9 +2531,9 @@ MidiRegionView::paste (nframes64_t pos, float times, const MidiCutBuffer& mcb)
 
                trackview.session()->begin_reversible_command (_("paste"));
 
-               XMLNode& before (_region->get_state());
+                _region->clear_history ();
                _region->set_length (end_frame, this);
-               trackview.session()->add_command (new MementoCommand<Region>(*_region, &before, &_region->get_state()));
+               trackview.session()->add_command (new StatefulDiffCommand (_region));
        }
 
        apply_delta ();