mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-23 15:16:25 +01:00
MidiView: fix display of out-of-range live (recording) notes
This involves better handling of note range changes, and also a renaming of member variables to better reflect their function. It adds _finished_live_notes to hold notes that were recorded live but have ended, since these also need to be updated as zooming or note range changes
This commit is contained in:
parent
68c69fb89d
commit
a0302bd7fc
3 changed files with 129 additions and 74 deletions
|
|
@ -434,7 +434,7 @@ MidiStreamView::update_rec_box ()
|
||||||
region->set_length (timecnt_t (_trackview.track()->current_capture_end () - _trackview.track()->current_capture_start()));
|
region->set_length (timecnt_t (_trackview.track()->current_capture_end () - _trackview.track()->current_capture_start()));
|
||||||
|
|
||||||
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rec_regions.back().second);
|
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rec_regions.back().second);
|
||||||
mrv->extend_active_notes ();
|
mrv->extend_unfinished_live_notes ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,8 +114,8 @@ MidiView::MidiView (std::shared_ptr<MidiTrack> mt,
|
||||||
uint32_t basic_color)
|
uint32_t basic_color)
|
||||||
: _editing_context (ec)
|
: _editing_context (ec)
|
||||||
, _midi_context (bg)
|
, _midi_context (bg)
|
||||||
, _active_notes (nullptr)
|
, _unfinished_live_notes (nullptr)
|
||||||
, active_note_end (std::numeric_limits<Temporal::Beats>::max())
|
, live_note_end (std::numeric_limits<Temporal::Beats>::max())
|
||||||
, _note_group (new ArdourCanvas::Container (&parent))
|
, _note_group (new ArdourCanvas::Container (&parent))
|
||||||
, _note_diff_command (nullptr)
|
, _note_diff_command (nullptr)
|
||||||
, _ghost_note (nullptr)
|
, _ghost_note (nullptr)
|
||||||
|
|
@ -153,8 +153,8 @@ MidiView::MidiView (MidiView const & other)
|
||||||
, _editing_context (other.editing_context())
|
, _editing_context (other.editing_context())
|
||||||
, _midi_context (other.midi_context())
|
, _midi_context (other.midi_context())
|
||||||
, _midi_region (other.midi_region())
|
, _midi_region (other.midi_region())
|
||||||
, _active_notes (nullptr)
|
, _unfinished_live_notes (nullptr)
|
||||||
, active_note_end (std::numeric_limits<Temporal::Beats>::max())
|
, live_note_end (std::numeric_limits<Temporal::Beats>::max())
|
||||||
, _note_group (new ArdourCanvas::Container (other._note_group->parent()))
|
, _note_group (new ArdourCanvas::Container (other._note_group->parent()))
|
||||||
, _note_diff_command (0)
|
, _note_diff_command (0)
|
||||||
, _ghost_note (nullptr)
|
, _ghost_note (nullptr)
|
||||||
|
|
@ -1162,7 +1162,7 @@ MidiView::model_changed()
|
||||||
|
|
||||||
EC_LOCAL_TEMPO_SCOPE_ARG (_editing_context);
|
EC_LOCAL_TEMPO_SCOPE_ARG (_editing_context);
|
||||||
|
|
||||||
if (_active_notes) {
|
if (_unfinished_live_notes) {
|
||||||
// Currently recording
|
// Currently recording
|
||||||
const samplecnt_t zoom = _editing_context.get_current_zoom();
|
const samplecnt_t zoom = _editing_context.get_current_zoom();
|
||||||
if (zoom != _last_display_zoom) {
|
if (zoom != _last_display_zoom) {
|
||||||
|
|
@ -1325,7 +1325,7 @@ MidiView::view_changed()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_active_notes) {
|
if (_unfinished_live_notes) {
|
||||||
|
|
||||||
/* Recording */
|
/* Recording */
|
||||||
|
|
||||||
|
|
@ -1599,7 +1599,7 @@ MidiView::~MidiView ()
|
||||||
|
|
||||||
delete _list_editor;
|
delete _list_editor;
|
||||||
|
|
||||||
if (_active_notes) {
|
if (_unfinished_live_notes) {
|
||||||
end_write();
|
end_write();
|
||||||
}
|
}
|
||||||
_entered_note = 0;
|
_entered_note = 0;
|
||||||
|
|
@ -1680,25 +1680,33 @@ MidiView::begin_write()
|
||||||
XXX this should not happen.
|
XXX this should not happen.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (_active_notes) {
|
if (_unfinished_live_notes) {
|
||||||
for (auto n = 0; n < 128; ++n) {
|
for (auto n = 0; n < 128; ++n) {
|
||||||
if (_active_notes[n]) {
|
if (_unfinished_live_notes[n]) {
|
||||||
auto iter = _events.find (_active_notes[n]->note());
|
auto iter = _events.find (_unfinished_live_notes[n]->note());
|
||||||
if (iter != _events.end()) {
|
if (iter != _events.end()) {
|
||||||
_events.erase (iter);
|
_events.erase (iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete [] _active_notes;
|
delete [] _unfinished_live_notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto & n : _finished_live_notes) {
|
||||||
|
auto iter = _events.find (n->note());
|
||||||
|
if (iter != _events.end()) {
|
||||||
|
_events.erase (iter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reallocate */
|
/* reallocate */
|
||||||
|
|
||||||
_active_notes = new Note*[128];
|
_unfinished_live_notes = new Note*[128];
|
||||||
for (unsigned i = 0; i < 128; ++i) {
|
for (size_t i = 0; i < 128; ++i) {
|
||||||
_active_notes[i] = nullptr;
|
_unfinished_live_notes[i] = nullptr;
|
||||||
}
|
}
|
||||||
active_note_end = timecnt_t (Temporal::BeatTime);
|
_finished_live_notes.clear ();
|
||||||
|
live_note_end = timecnt_t (Temporal::BeatTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1711,42 +1719,43 @@ MidiView::end_write()
|
||||||
owned by _events. Just delete the container used for active
|
owned by _events. Just delete the container used for active
|
||||||
notes only.
|
notes only.
|
||||||
*/
|
*/
|
||||||
delete [] _active_notes;
|
delete [] _unfinished_live_notes;
|
||||||
_active_notes = nullptr;
|
_unfinished_live_notes = nullptr;
|
||||||
|
_finished_live_notes.clear ();
|
||||||
|
|
||||||
_marked_for_selection.clear();
|
_marked_for_selection.clear();
|
||||||
_marked_for_velocity.clear();
|
_marked_for_velocity.clear();
|
||||||
active_note_end = std::numeric_limits<Temporal::Beats>::max();
|
live_note_end = std::numeric_limits<Temporal::Beats>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Extend active notes to rightmost edge of region (if length is changed)
|
/** Extend active notes to rightmost edge of region (if length is changed)
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
MidiView::extend_active_notes()
|
MidiView::extend_unfinished_live_notes()
|
||||||
{
|
{
|
||||||
if (!_midi_region) {
|
if (!_midi_region) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
extend_active_notes (_midi_region->length());
|
extend_unfinished_live_notes (_midi_region->length());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiView::extend_active_notes (timecnt_t const & duration)
|
MidiView::extend_unfinished_live_notes (timecnt_t const & duration)
|
||||||
{
|
{
|
||||||
if (!_midi_region) {
|
if (!_midi_region) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_active_notes) {
|
if (!_unfinished_live_notes) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
double x1 = _editing_context.duration_to_pixels (duration);
|
double x1 = _editing_context.duration_to_pixels (duration);
|
||||||
|
|
||||||
for (int i = 0; i < 128; ++i) {
|
for (int i = 0; i < 128; ++i) {
|
||||||
if (_active_notes[i]) {
|
if (_unfinished_live_notes[i]) {
|
||||||
_active_notes[i]->set_x1 (x1);
|
_unfinished_live_notes[i]->set_x1 (x1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1854,8 +1863,8 @@ MidiView::update_sustained (Note* ev)
|
||||||
ev->set_velocity (note->velocity()/127.0);
|
ev->set_velocity (note->velocity()/127.0);
|
||||||
|
|
||||||
if (note->end_time() == std::numeric_limits<Temporal::Beats>::max()) {
|
if (note->end_time() == std::numeric_limits<Temporal::Beats>::max()) {
|
||||||
if (_active_notes && note->note() < 128) {
|
if (_unfinished_live_notes && note->note() < 128) {
|
||||||
Note* const old_nb = _active_notes[note->note()];
|
Note* const old_nb = _unfinished_live_notes[note->note()];
|
||||||
if (old_nb && (old_nb != ev)) {
|
if (old_nb && (old_nb != ev)) {
|
||||||
/* There is an active note on this key, so we have a stuck
|
/* There is an active note on this key, so we have a stuck
|
||||||
note. Finish the old rectangle here.
|
note. Finish the old rectangle here.
|
||||||
|
|
@ -1866,7 +1875,7 @@ MidiView::update_sustained (Note* ev)
|
||||||
/* XXX we now leak old_nb if it was set since there are
|
/* XXX we now leak old_nb if it was set since there are
|
||||||
* no other references to it, plus it will remain on-screen
|
* no other references to it, plus it will remain on-screen
|
||||||
*/
|
*/
|
||||||
_active_notes[note->note()] = ev;
|
_unfinished_live_notes[note->note()] = ev;
|
||||||
}
|
}
|
||||||
/* outline all but right edge */
|
/* outline all but right edge */
|
||||||
ev->set_outline_what (ArdourCanvas::Rectangle::What (
|
ev->set_outline_what (ArdourCanvas::Rectangle::What (
|
||||||
|
|
@ -1878,6 +1887,14 @@ MidiView::update_sustained (Note* ev)
|
||||||
ev->set_outline_all ();
|
ev->set_outline_all ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool visible ((y0 >= 0) && (y1 <= _midi_context.contents_height()));
|
||||||
|
|
||||||
|
if (!visible) {
|
||||||
|
ev->hide ();
|
||||||
|
} else {
|
||||||
|
ev->show ();
|
||||||
|
}
|
||||||
|
|
||||||
color_note (ev, note->channel());
|
color_note (ev, note->channel());
|
||||||
ev->set_ignore_events (!note_editable (ev));
|
ev->set_ignore_events (!note_editable (ev));
|
||||||
}
|
}
|
||||||
|
|
@ -1916,7 +1933,7 @@ MidiView::clip_capture_update_sustained (Note *ev, double& x0, double& x1, doubl
|
||||||
|
|
||||||
/* normal note */
|
/* normal note */
|
||||||
|
|
||||||
timepos_t ane = active_note_end.end();
|
timepos_t ane = live_note_end.end();
|
||||||
|
|
||||||
if (ane.beats() != std::numeric_limits<Temporal::Beats>::max()) {
|
if (ane.beats() != std::numeric_limits<Temporal::Beats>::max()) {
|
||||||
if (note_end > ane) {
|
if (note_end > ane) {
|
||||||
|
|
@ -1930,7 +1947,7 @@ MidiView::clip_capture_update_sustained (Note *ev, double& x0, double& x1, doubl
|
||||||
|
|
||||||
/* nascent note currently being recorded, noteOff has not yet arrived */
|
/* nascent note currently being recorded, noteOff has not yet arrived */
|
||||||
|
|
||||||
x1 = x0 + std::max (1., _editing_context.duration_to_pixels (note_start.distance (active_note_end.end())));
|
x1 = x0 + std::max (1., _editing_context.duration_to_pixels (note_start.distance (live_note_end.end())));
|
||||||
}
|
}
|
||||||
|
|
||||||
y1 = y0 + std::max (1., note_height() - 1.);
|
y1 = y0 + std::max (1., note_height() - 1.);
|
||||||
|
|
@ -4707,15 +4724,15 @@ MidiView::clip_data_recorded (samplecnt_t total_duration)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_active_notes) {
|
if (!_unfinished_live_notes) {
|
||||||
/* left over idle callback, but we're not recording */
|
/* left over idle callback, but we're not recording */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_active_notes) {
|
if (_unfinished_live_notes) {
|
||||||
for (int n = 0; n < 128; ++n) {
|
for (int n = 0; n < 128; ++n) {
|
||||||
if (_active_notes[n]) {
|
if (_unfinished_live_notes[n]) {
|
||||||
update_sustained (_active_notes[n]);
|
update_sustained (_unfinished_live_notes[n]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4724,6 +4741,7 @@ MidiView::clip_data_recorded (samplecnt_t total_duration)
|
||||||
assert (tb);
|
assert (tb);
|
||||||
|
|
||||||
std::shared_ptr<MidiBuffer> buf = tb->get_gui_feed_buffer();
|
std::shared_ptr<MidiBuffer> buf = tb->get_gui_feed_buffer();
|
||||||
|
bool note_range_changed = false;
|
||||||
|
|
||||||
for (MidiBuffer::iterator i = buf->begin(); i != buf->end(); ++i) {
|
for (MidiBuffer::iterator i = buf->begin(); i != buf->end(); ++i) {
|
||||||
const Evoral::Event<MidiBuffer::TimeType>& ev = *i;
|
const Evoral::Event<MidiBuffer::TimeType>& ev = *i;
|
||||||
|
|
@ -4747,36 +4765,53 @@ MidiView::clip_data_recorded (samplecnt_t total_duration)
|
||||||
|
|
||||||
std::shared_ptr<NoteType> note (new NoteType (ev.channel(), time_beats, std::numeric_limits<Temporal::Beats>::max() - time_beats, ev.note(), ev.velocity()));
|
std::shared_ptr<NoteType> note (new NoteType (ev.channel(), time_beats, std::numeric_limits<Temporal::Beats>::max() - time_beats, ev.note(), ev.velocity()));
|
||||||
|
|
||||||
NoteBase* nb = add_note (note, true);
|
if (ev.note() < _midi_context.lowest_note()) {
|
||||||
|
_midi_context.update_data_note_range (ev.note(), _midi_context.highest_note());
|
||||||
|
note_range_changed |= set_note_range (ev.note(), _midi_context.highest_note());
|
||||||
|
} else if (ev.note() > _midi_context.highest_note()) {
|
||||||
|
_midi_context.update_data_note_range (_midi_context.lowest_note(), ev.note());
|
||||||
|
note_range_changed |= set_note_range (_midi_context.lowest_note(), ev.note());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const int y = _midi_context.note_to_y (note->note());
|
||||||
|
bool visible = (y >= 0) && (y <= _midi_context.contents_height());
|
||||||
|
|
||||||
|
NoteBase* nb = add_note (note, visible);
|
||||||
nb->item()->set_fill_color (UIConfiguration::instance().color ("recording note"));
|
nb->item()->set_fill_color (UIConfiguration::instance().color ("recording note"));
|
||||||
nb->item()->set_outline_color (UIConfiguration::instance().color ("recording note"));
|
nb->item()->set_outline_color (UIConfiguration::instance().color ("recording note"));
|
||||||
|
|
||||||
/* fix up our note range */
|
|
||||||
if (ev.note() < _midi_context.lowest_note()) {
|
|
||||||
set_note_range (ev.note(), _midi_context.highest_note());
|
|
||||||
} else if (ev.note() > _midi_context.highest_note()) {
|
|
||||||
set_note_range (_midi_context.lowest_note(), ev.note());
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (ev.type() == MIDI_CMD_NOTE_OFF) {
|
} else if (ev.type() == MIDI_CMD_NOTE_OFF) {
|
||||||
|
|
||||||
// XXX WAS resolve_note (ev.note (), time_beats);
|
// XXX WAS resolve_note (ev.note (), time_beats);
|
||||||
uint8_t note = ev.note ();
|
uint8_t note = ev.note ();
|
||||||
Temporal::Beats end_time = time_beats;
|
Temporal::Beats end_time = time_beats;
|
||||||
|
|
||||||
if (_active_notes && _active_notes[note]) {
|
if (_unfinished_live_notes && _unfinished_live_notes[note]) {
|
||||||
/* Set note length so update_note() works. Note this is a local note
|
/* Set note length so update_note() works. Note this is a local note
|
||||||
for recording, not from a model, so we can safely mess with it. */
|
for recording, not from a model, so we can safely mess with it. */
|
||||||
_active_notes[note]->note()->set_length (end_time - _active_notes[note]->note()->time());
|
_unfinished_live_notes[note]->note()->set_length (end_time - _unfinished_live_notes[note]->note()->time());
|
||||||
|
|
||||||
_active_notes[note]->set_x1 (_editing_context.sample_to_pixel (timepos_t (ev.time ()).samples()));
|
_unfinished_live_notes[note]->set_x1 (_editing_context.sample_to_pixel (timepos_t (ev.time ()).samples()));
|
||||||
_active_notes[note]->set_outline_all ();
|
_unfinished_live_notes[note]->set_outline_all ();
|
||||||
_active_notes[note] = nullptr;
|
_unfinished_live_notes[note] = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
active_note_end = timecnt_t (total_duration);
|
if (note_range_changed) {
|
||||||
|
assert (_unfinished_live_notes);
|
||||||
|
for (size_t n = 0; n < 128; ++n) {
|
||||||
|
if (_unfinished_live_notes[n]) {
|
||||||
|
update_note (_unfinished_live_notes[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto & n : _finished_live_notes) {
|
||||||
|
update_note (n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
live_note_end = timecnt_t (total_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called when a diskstream on our track has received some data. Update the view, if applicable.
|
/** Called when a diskstream on our track has received some data. Update the view, if applicable.
|
||||||
|
|
@ -4793,7 +4828,7 @@ MidiView::data_recorded (std::weak_ptr<MidiSource> w)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_active_notes) {
|
if (!_unfinished_live_notes) {
|
||||||
/* we aren't actively being recorded to */
|
/* we aren't actively being recorded to */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -4807,6 +4842,7 @@ MidiView::data_recorded (std::weak_ptr<MidiSource> w)
|
||||||
std::shared_ptr<MidiBuffer> buf = _midi_track->get_gui_feed_buffer ();
|
std::shared_ptr<MidiBuffer> buf = _midi_track->get_gui_feed_buffer ();
|
||||||
|
|
||||||
samplepos_t back = max_samplepos;
|
samplepos_t back = max_samplepos;
|
||||||
|
bool note_range_changed = false;
|
||||||
|
|
||||||
for (MidiBuffer::iterator i = buf->begin(); i != buf->end(); ++i) {
|
for (MidiBuffer::iterator i = buf->begin(); i != buf->end(); ++i) {
|
||||||
const Evoral::Event<MidiBuffer::TimeType>& ev = *i;
|
const Evoral::Event<MidiBuffer::TimeType>& ev = *i;
|
||||||
|
|
@ -4833,27 +4869,32 @@ MidiView::data_recorded (std::weak_ptr<MidiSource> w)
|
||||||
|
|
||||||
assert (note->end_time() == std::numeric_limits<Temporal::Beats>::max());
|
assert (note->end_time() == std::numeric_limits<Temporal::Beats>::max());
|
||||||
|
|
||||||
NoteBase* nb = add_note (note, true);
|
if (ev.note() < _midi_context.lowest_note()) {
|
||||||
|
_midi_context.update_data_note_range (ev.note(), _midi_context.highest_note());
|
||||||
|
note_range_changed |= set_note_range (ev.note(), _midi_context.highest_note());
|
||||||
|
} else if (ev.note() > _midi_context.highest_note()) {
|
||||||
|
_midi_context.update_data_note_range (_midi_context.lowest_note(), ev.note());
|
||||||
|
note_range_changed |= set_note_range (_midi_context.lowest_note(), ev.note());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const int y = _midi_context.note_to_y (note->note());
|
||||||
|
bool visible = (y >= 0) && (y <= _midi_context.contents_height());
|
||||||
|
|
||||||
|
NoteBase* nb = add_note (note, visible);
|
||||||
nb->item()->set_fill_color (UIConfiguration::instance().color ("recording note"));
|
nb->item()->set_fill_color (UIConfiguration::instance().color ("recording note"));
|
||||||
nb->item()->set_outline_color (UIConfiguration::instance().color ("recording note"));
|
nb->item()->set_outline_color (UIConfiguration::instance().color ("recording note"));
|
||||||
|
|
||||||
/* fix up our note range */
|
|
||||||
if (ev.note() < _midi_context.lowest_note()) {
|
|
||||||
set_note_range (ev.note(), _midi_context.highest_note());
|
|
||||||
} else if (ev.note() > _midi_context.highest_note()) {
|
|
||||||
set_note_range (_midi_context.lowest_note(), ev.note());
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (ev.type() == MIDI_CMD_NOTE_OFF) {
|
} else if (ev.type() == MIDI_CMD_NOTE_OFF) {
|
||||||
|
|
||||||
// XXX WAS resolve_note (ev.note (), time_beats);
|
// XXX WAS resolve_note (ev.note (), time_beats);
|
||||||
uint8_t note = ev.note ();
|
uint8_t note = ev.note ();
|
||||||
Temporal::Beats end_time = time_beats;
|
Temporal::Beats end_time = time_beats;
|
||||||
|
|
||||||
if (_active_notes && _active_notes[note]) {
|
if (_unfinished_live_notes && _unfinished_live_notes[note]) {
|
||||||
/* Set note length so update_note() works. Note this is a local note
|
/* Set note length so update_note() works. Note this is a local note
|
||||||
for recording, not from a model, so we can safely mess with it. */
|
for recording, not from a model, so we can safely mess with it. */
|
||||||
_active_notes[note]->note()->set_length (end_time - _active_notes[note]->note()->time());
|
_unfinished_live_notes[note]->note()->set_length (end_time - _unfinished_live_notes[note]->note()->time());
|
||||||
|
|
||||||
/* End time is relative to the source being recorded. */
|
/* End time is relative to the source being recorded. */
|
||||||
|
|
||||||
|
|
@ -4863,15 +4904,28 @@ MidiView::data_recorded (std::weak_ptr<MidiSource> w)
|
||||||
// - and then take the samples() value of that and convert it to pixels
|
// - and then take the samples() value of that and convert it to pixels
|
||||||
//
|
//
|
||||||
// Much simpler to just use ev.time() which is already the absolute position (in sample-time)
|
// Much simpler to just use ev.time() which is already the absolute position (in sample-time)
|
||||||
_active_notes[note]->set_x1 (_editing_context.sample_to_pixel ((src->time_since_capture_start (timepos_t (ev.time ()))).samples()));
|
_unfinished_live_notes[note]->set_x1 (_editing_context.sample_to_pixel ((src->time_since_capture_start (timepos_t (ev.time ()))).samples()));
|
||||||
_active_notes[note]->set_outline_all ();
|
_unfinished_live_notes[note]->set_outline_all ();
|
||||||
_active_notes[note] = nullptr;
|
_finished_live_notes.push_back (_unfinished_live_notes[note]);
|
||||||
|
_unfinished_live_notes[note] = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
back = ev.time ();
|
back = ev.time ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (note_range_changed) {
|
||||||
|
assert (_unfinished_live_notes);
|
||||||
|
for (size_t n = 0; n < 128; ++n) {
|
||||||
|
if (_unfinished_live_notes[n]) {
|
||||||
|
update_note (_unfinished_live_notes[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto & n : _finished_live_notes) {
|
||||||
|
update_note (n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_midi_context.record_layer_check (_midi_region, back);
|
_midi_context.record_layer_check (_midi_region, back);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5297,7 +5351,7 @@ struct NoteExtentInfo
|
||||||
void
|
void
|
||||||
MidiView::join_notes_on_channel (int chn)
|
MidiView::join_notes_on_channel (int chn)
|
||||||
{
|
{
|
||||||
NoteExtentInfo ninfo[127];
|
NoteExtentInfo ninfo[128];
|
||||||
|
|
||||||
for (auto & s : _selection) {
|
for (auto & s : _selection) {
|
||||||
|
|
||||||
|
|
@ -5329,7 +5383,7 @@ MidiView::join_notes_on_channel (int chn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t n = 0; n < 127; ++n) {
|
for (size_t n = 0; n < 128; ++n) {
|
||||||
|
|
||||||
NoteExtentInfo& ni (ninfo[n]);
|
NoteExtentInfo& ni (ninfo[n]);
|
||||||
|
|
||||||
|
|
@ -5445,16 +5499,16 @@ MidiView::height() const
|
||||||
return _midi_context.height();
|
return _midi_context.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
MidiView::set_note_range (uint8_t low, uint8_t high)
|
MidiView::set_note_range (uint8_t low, uint8_t high)
|
||||||
{
|
{
|
||||||
_midi_context.apply_note_range (low, high, true);
|
return _midi_context.apply_note_range (low, high, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
MidiView::maybe_set_note_range (uint8_t low, uint8_t high)
|
MidiView::maybe_set_note_range (uint8_t low, uint8_t high)
|
||||||
{
|
{
|
||||||
_midi_context.maybe_apply_note_range (low, high, true);
|
return _midi_context.maybe_apply_note_range (low, high, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -183,8 +183,8 @@ class MidiView : public virtual sigc::trackable, public LineMerger
|
||||||
|
|
||||||
void begin_write ();
|
void begin_write ();
|
||||||
void end_write ();
|
void end_write ();
|
||||||
void extend_active_notes ();
|
void extend_unfinished_live_notes ();
|
||||||
void extend_active_notes (Temporal::timecnt_t const &);
|
void extend_unfinished_live_notes (Temporal::timecnt_t const &);
|
||||||
|
|
||||||
virtual void begin_drag_edit (std::string const & why);
|
virtual void begin_drag_edit (std::string const & why);
|
||||||
void end_drag_edit ();
|
void end_drag_edit ();
|
||||||
|
|
@ -308,8 +308,8 @@ class MidiView : public virtual sigc::trackable, public LineMerger
|
||||||
|
|
||||||
void show_list_editor ();
|
void show_list_editor ();
|
||||||
|
|
||||||
void set_note_range (uint8_t low, uint8_t high);
|
bool set_note_range (uint8_t low, uint8_t high);
|
||||||
void maybe_set_note_range (uint8_t low, uint8_t high);
|
bool maybe_set_note_range (uint8_t low, uint8_t high);
|
||||||
virtual void set_visibility_note_range (MidiViewBackground::VisibleNoteRange, bool);
|
virtual void set_visibility_note_range (MidiViewBackground::VisibleNoteRange, bool);
|
||||||
|
|
||||||
typedef std::set<NoteBase*> Selection;
|
typedef std::set<NoteBase*> Selection;
|
||||||
|
|
@ -513,8 +513,9 @@ class MidiView : public virtual sigc::trackable, public LineMerger
|
||||||
CopyDragEvents _copy_drag_events;
|
CopyDragEvents _copy_drag_events;
|
||||||
PatchChanges _patch_changes;
|
PatchChanges _patch_changes;
|
||||||
SysExes _sys_exes;
|
SysExes _sys_exes;
|
||||||
Note** _active_notes;
|
Note** _unfinished_live_notes;
|
||||||
Temporal::timecnt_t active_note_end;
|
std::vector<Note*> _finished_live_notes;
|
||||||
|
Temporal::timecnt_t live_note_end;
|
||||||
ArdourCanvas::Container* _note_group;
|
ArdourCanvas::Container* _note_group;
|
||||||
ARDOUR::MidiModel::NoteDiffCommand* _note_diff_command;
|
ARDOUR::MidiModel::NoteDiffCommand* _note_diff_command;
|
||||||
NoteBase* _ghost_note;
|
NoteBase* _ghost_note;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue