fix erroneous deletion of notes after MIDI clip recording

If an idle data captured callback executed AFTER the code trigger by capture
end, it would call ::begin_write() which would end up calling clear_events()
which would delete all notes in the correctly setup MidiView.

Now, the idle data capture callback no longer does anything of significance if
the TriggerBox is not actively recording. In addition, we do not call
begin_write() in the MidiView if it is not already set up for capture
display (this is triggered by changes in the TriggerBox's record enable state
and the first data captured callback from an RT thread. Further,
::begin_write(), if called, only deletes notes that were in
_active_notes (though this should probably never happen).
This commit is contained in:
Paul Davis
2025-05-16 15:10:48 -06:00
parent c3a4026ace
commit 0ddb9fa8e2
2 changed files with 30 additions and 13 deletions

View File

@@ -1622,11 +1622,14 @@ MidiView::begin_write()
XXX this should not happen.
*/
clear_events ();
if (_active_notes) {
for (unsigned i = 0; i < 128; ++i) {
delete _active_notes[i];
for (auto n = 0; n < 128; ++n) {
if (_active_notes[n]) {
auto iter = _events.find (_active_notes[n]->note());
if (iter != _events.end()) {
_events.erase (iter);
}
}
}
delete [] _active_notes;
}
@@ -1646,15 +1649,13 @@ MidiView::begin_write()
void
MidiView::end_write()
{
if (_active_notes) {
/* do not delete individual notes referenced here, because they are
owned by _events. Just delete the container used for active
notes only.
*/
delete [] _active_notes;
}
/* do not delete individual notes referenced here, because they are
owned by _events. Just delete the container used for active
notes only.
*/
delete [] _active_notes;
_active_notes = nullptr;
_marked_for_selection.clear();
_marked_for_velocity.clear();
active_note_end = std::numeric_limits<Temporal::Beats>::max();
@@ -4622,7 +4623,8 @@ MidiView::clip_data_recorded (samplecnt_t total_duration)
}
if (!_active_notes) {
begin_write ();
/* left over idle callback, but we're not recording */
return;
}
if (_active_notes) {

View File

@@ -959,6 +959,18 @@ Pianoroll::data_captured (samplecnt_t total_duration)
bool
Pianoroll::idle_data_captured ()
{
if (!ref.box()) {
return false;
}
switch (ref.box()->record_enabled()) {
case Recording:
break;
default:
std::cerr << "Idle data callback but no longer recording\n";
return false;
}
double where = sample_to_pixel_unrounded (data_capture_duration);
if (where > _visible_canvas_width * 0.80) {
@@ -2252,6 +2264,9 @@ Pianoroll::rec_enable_change ()
case Recording:
rec_enable_button.set_active_state (Gtkmm2ext::ExplicitActive);
rec_blink_connection.disconnect ();
if (view) {
view->begin_write ();
}
break;
case Enabled:
if (!UIConfiguration::instance().get_no_strobe() && ref.trigger()->armed()) {