X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fmidi_region_view.cc;h=26490f76e73ef0e79f26188f2db1bc03f9853ee4;hb=792e3de1d4cb291a02c5c31dad54028049bafed9;hp=40f267717b6d03c9337c4a1acf9def2dd97e006b;hpb=cb8407d26fb8863b2434aa6006da32c3f732e663;p=ardour.git diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 40f267717b..26490f76e7 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -29,14 +29,15 @@ #include #include "pbd/memento_command.h" +#include "pbd/stateful_diff_command.h" #include "ardour/playlist.h" #include "ardour/tempo.h" #include "ardour/midi_region.h" #include "ardour/midi_source.h" -#include "ardour/midi_diskstream.h" #include "ardour/midi_model.h" #include "ardour/midi_patch_manager.h" +#include "ardour/session.h" #include "evoral/Parameter.hpp" #include "evoral/Control.hpp" @@ -64,11 +65,11 @@ #include "i18n.h" -using namespace sigc; using namespace ARDOUR; using namespace PBD; using namespace Editing; using namespace ArdourCanvas; +using Gtkmm2ext::Keyboard; MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr r, double spu, Gdk::Color const & basic_color) @@ -88,6 +89,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(); } @@ -109,6 +112,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(); @@ -131,6 +136,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; @@ -156,6 +163,8 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptrraise_to_top(); - group->signal_event().connect (mem_fun (this, &MidiRegionView::canvas_event), false); + group->signal_event().connect (sigc::mem_fun (this, &MidiRegionView::canvas_event), false); midi_view()->signal_channel_mode_changed().connect( - mem_fun(this, &MidiRegionView::midi_channel_mode_changed)); + sigc::mem_fun(this, &MidiRegionView::midi_channel_mode_changed)); midi_view()->signal_midi_patch_settings_changed().connect( - mem_fun(this, &MidiRegionView::midi_patch_settings_changed)); + sigc::mem_fun(this, &MidiRegionView::midi_patch_settings_changed)); } bool @@ -516,8 +525,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. @@ -551,7 +562,7 @@ MidiRegionView::create_note_at(double x, double y, double length) MidiModel::DeltaCommand* cmd = _model->new_delta_command("add note"); cmd->add(new_note); - _model->apply_command(trackview.session(), cmd); + _model->apply_command(*trackview.session(), cmd); play_midi_note (new_note); } @@ -584,7 +595,8 @@ MidiRegionView::display_model(boost::shared_ptr model) { _model = model; content_connection.disconnect (); - content_connection = _model->ContentsChanged.connect(sigc::mem_fun(this, &MidiRegionView::redisplay_model)); + _model->ContentsChanged.connect (content_connection, invalidator (*this), boost::bind (&MidiRegionView::redisplay_model, this), gui_context()); + clear_events (); if (_enable_display) { @@ -663,9 +675,9 @@ MidiRegionView::apply_delta() _marked_for_selection.insert((*i)->note()); } - _model->apply_command(trackview.session(), _delta_command); + _model->apply_command(*trackview.session(), _delta_command); _delta_command = 0; - midi_view()->midi_track()->diskstream()->playlist_modified(); + midi_view()->midi_track()->playlist_modified(); _marked_for_selection.clear(); _marked_for_velocity.clear(); @@ -678,9 +690,9 @@ MidiRegionView::apply_diff () return; } - _model->apply_command(trackview.session(), _diff_command); + _model->apply_command(*trackview.session(), _diff_command); _diff_command = 0; - midi_view()->midi_track()->diskstream()->playlist_modified(); + midi_view()->midi_track()->playlist_modified(); _marked_for_velocity.clear(); } @@ -697,9 +709,9 @@ MidiRegionView::apply_delta_as_subcommand() _marked_for_selection.insert((*i)->note()); } - _model->apply_command_as_subcommand(trackview.session(), _delta_command); + _model->apply_command_as_subcommand(*trackview.session(), _delta_command); _delta_command = 0; - midi_view()->midi_track()->diskstream()->playlist_modified(); + midi_view()->midi_track()->playlist_modified(); _marked_for_selection.clear(); _marked_for_velocity.clear(); @@ -717,9 +729,9 @@ MidiRegionView::apply_diff_as_subcommand() _marked_for_selection.insert((*i)->note()); } - _model->apply_command_as_subcommand(trackview.session(), _diff_command); + _model->apply_command_as_subcommand(*trackview.session(), _diff_command); _diff_command = 0; - midi_view()->midi_track()->diskstream()->playlist_modified(); + midi_view()->midi_track()->playlist_modified(); _marked_for_selection.clear(); _marked_for_velocity.clear(); @@ -772,7 +784,7 @@ MidiRegionView::redisplay_model() (*i)->invalidate (); } - _model->read_lock(); + MidiModel::ReadLock lock(_model->read_lock()); MidiModel::Notes& notes (_model->notes()); _optimization_iterator = _events.begin(); @@ -832,8 +844,6 @@ MidiRegionView::redisplay_model() display_sysexes(); display_program_changes(); - _model->read_unlock(); - _marked_for_selection.clear (); _marked_for_velocity.clear (); @@ -938,6 +948,8 @@ MidiRegionView::~MidiRegionView () { in_destructor = true; + delete _list_editor; + RegionViewGoingAway (this); /* EMIT_SIGNAL */ if (_active_notes) { @@ -951,11 +963,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 +1083,7 @@ MidiRegionView::add_ghost (TimeAxisView& tv) } } - ghost->GoingAway.connect (mem_fun(*this, &MidiRegionView::remove_ghost)); + GhostRegion::CatchDeletion.connect (*this, invalidator (*this), ui_bind (&RegionView::remove_ghost, this, _1), gui_context()); return ghost; } @@ -1139,7 +1151,7 @@ MidiRegionView::extend_active_notes() void MidiRegionView::play_midi_note(boost::shared_ptr note) { - if (!trackview.editor().sound_notes()) { + if (no_sound_notes || !trackview.editor().sound_notes()) { return; } @@ -1151,8 +1163,8 @@ MidiRegionView::play_midi_note(boost::shared_ptr note) const double note_length_beats = (note->off_event().time() - note->on_event().time()); nframes_t note_length_ms = beats_to_frames(note_length_beats) - * (1000 / (double)route_ui->session().nominal_frame_rate()); - Glib::signal_timeout().connect(bind(mem_fun(this, &MidiRegionView::play_midi_note_off), note), + * (1000 / (double)route_ui->session()->nominal_frame_rate()); + Glib::signal_timeout().connect(sigc::bind(sigc::mem_fun(this, &MidiRegionView::play_midi_note_off), note), note_length_ms, G_PRIORITY_DEFAULT); } @@ -1522,6 +1534,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 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 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) { @@ -1659,6 +1756,7 @@ MidiRegionView::add_to_selection (CanvasNoteEvent* ev) } if (_selection.insert (ev).second) { + cerr << "Added CNE to selection, size now " << _selection.size() << endl; ev->selected (true); play_midi_note ((ev)->note()); } @@ -2204,9 +2302,15 @@ MidiRegionView::nudge_notes (bool forward) nframes64_t unused; nframes64_t distance; - if ((distance = trackview.editor().get_nudge_distance (ref_point, unused)) == 0) { + if (trackview.editor().snap_mode() == Editing::SnapOff) { + + /* grid is off - use nudge distance */ - /* no nudge distance set - use grid */ + distance = trackview.editor().get_nudge_distance (ref_point, unused); + + } else { + + /* use grid */ nframes64_t next_pos = ref_point; @@ -2266,11 +2370,12 @@ MidiRegionView::note_entered(ArdourCanvas::CanvasNoteEvent* ev) note_selected(ev, true); } - PublicEditor& editor (trackview.editor()); char buf[4]; snprintf (buf, sizeof (buf), "%d", (int) ev->note()->note()); + // This causes an infinite loop on note add sometimes + //PublicEditor& editor (trackview.editor()); //editor.show_verbose_canvas_cursor_with (Evoral::midi_note_name (ev->note()->note())); - editor.show_verbose_canvas_cursor_with (buf); + //editor.show_verbose_canvas_cursor_with (buf); } void @@ -2370,8 +2475,12 @@ MidiRegionView::selection_as_cut_buffer () const { Notes notes; + cerr << "Convert selection of " << _selection.size() << " into a cut buffer\n"; + for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) { - notes.insert (boost::shared_ptr (new NoteType (*((*i)->note().get())))); + NoteType* n = (*i)->note().get(); + cerr << "CNE's note is " << n << endl; + notes.insert (boost::shared_ptr (new NoteType (*n))); } MidiCutBuffer* cb = new MidiCutBuffer (trackview.session()); @@ -2424,11 +2533,11 @@ MidiRegionView::paste (nframes64_t pos, float times, const MidiCutBuffer& mcb) if (end_frame > region_end) { - trackview.session().begin_reversible_command (_("paste")); + 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, &before, &_region->get_state())); + trackview.session()->add_command (new StatefulDiffCommand (_region)); } apply_delta (); @@ -2521,5 +2630,3 @@ MidiRegionView::selection_as_notelist (Notes& selected) } } } - -