#include <sigc++/signal.h>
#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"
, _pressed_button(0)
, _sort_needed (true)
, _optimization_iterator (_events.end())
+ , _list_editor (0)
+ , no_sound_notes (false)
{
_note_group->raise_to_top();
}
, _pressed_button(0)
, _sort_needed (true)
, _optimization_iterator (_events.end())
+ , _list_editor (0)
+ , no_sound_notes (false)
{
_note_group->raise_to_top();
, _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;
, _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;
region_muted ();
region_sync_changed ();
- region_resized (BoundsChanged);
+ region_resized (ARDOUR::bounds_change);
region_locked ();
reset_width_dependent_items (_pixel_width);
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.
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);
}
{
_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) {
_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();
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();
}
_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();
_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();
{
in_destructor = true;
+ delete _list_editor;
+
RegionViewGoingAway (this); /* EMIT_SIGNAL */
if (_active_notes) {
}
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();
}
}
- ghost->GoingAway.connect (sigc::mem_fun(*this, &MidiRegionView::remove_ghost));
+ GhostRegion::CatchDeletion.connect (*this, invalidator (*this), ui_bind (&RegionView::remove_ghost, this, _1), gui_context());
return ghost;
}
void
MidiRegionView::play_midi_note(boost::shared_ptr<NoteType> note)
{
- if (!trackview.editor().sound_notes()) {
+ if (no_sound_notes || !trackview.editor().sound_notes()) {
return;
}
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());
+ * (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);
}
}
}
+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)
{
}
if (_selection.insert (ev).second) {
+ cerr << "Added CNE to selection, size now " << _selection.size() << endl;
ev->selected (true);
play_midi_note ((ev)->note());
}
{
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<NoteType> (new NoteType (*((*i)->note().get()))));
+ NoteType* n = (*i)->note().get();
+ cerr << "CNE's note is " << n << endl;
+ notes.insert (boost::shared_ptr<NoteType> (new NoteType (*n)));
}
MidiCutBuffer* cb = new MidiCutBuffer (trackview.session());
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>(*_region, &before, &_region->get_state()));
+ trackview.session()->add_command (new StatefulDiffCommand (_region));
}
apply_delta ();