From ab2af5d185d0346ab1ef4e6f3e69138f3f708958 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 2 May 2008 20:57:27 +0000 Subject: [PATCH] Fix several crashes on MIDI recording. Fix MIDI CC iterator infinite looping. Only allocate Text widget for MIDI events if necessary. git-svn-id: svn://localhost/ardour2/branches/3.0@3307 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/canvas-note-event.cc | 29 +++++++++++++++++------------ gtk2_ardour/midi_streamview.cc | 13 +++++++------ libs/ardour/midi_model.cc | 12 +++++++----- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/gtk2_ardour/canvas-note-event.cc b/gtk2_ardour/canvas-note-event.cc index d775514b1f..149ad755ac 100644 --- a/gtk2_ardour/canvas-note-event.cc +++ b/gtk2_ardour/canvas-note-event.cc @@ -41,25 +41,29 @@ CanvasNoteEvent::CanvasNoteEvent(MidiRegionView& region, Item* item, , _note(note) , _selected(false) { - _text = new Text(*(item->property_parent())); } CanvasNoteEvent::~CanvasNoteEvent() { - if(_text) delete _text; - if(_channel_selector_widget) delete _channel_selector_widget; + if (_text) + delete _text; + + if (_channel_selector_widget) + delete _channel_selector_widget; } void CanvasNoteEvent::move_event(double dx, double dy) { _item->move(dx, dy); - _text->move(dx, dy); + if (_text) + _text->move(dx, dy); } void CanvasNoteEvent::show_velocity(void) { + _text = new Text(*(_item->property_parent())); _text->property_x() = (x1() + x2()) /2; _text->property_y() = (y1() + y2()) /2; ostringstream velo(ios::ate); @@ -75,14 +79,15 @@ CanvasNoteEvent::show_velocity(void) void CanvasNoteEvent::hide_velocity(void) { - _text->hide(); + delete _text; + _text = NULL; } void CanvasNoteEvent::on_channel_selection_change(uint16_t selection) { // make note change its color if its channel is not marked active - if( (selection & (1 << _note->channel())) == 0 ) { + if ( (selection & (1 << _note->channel())) == 0 ) { set_fill_color(ARDOUR_UI::config()->canvasvar_MidiNoteFillInactiveChannel.get()); set_outline_color(ARDOUR_UI::config()->canvasvar_MidiNoteOutlineInactiveChannel.get()); } else { @@ -105,7 +110,7 @@ CanvasNoteEvent::on_channel_change(uint8_t channel) void CanvasNoteEvent::show_channel_selector(void) { - if(_channel_selector_widget == 0) { + if (_channel_selector_widget == 0) { cerr << "Note has channel: " << int(_note->channel()) << endl; SingleMidiChannelSelector* _channel_selector = new SingleMidiChannelSelector(_note->channel()); _channel_selector->show_all(); @@ -131,7 +136,7 @@ CanvasNoteEvent::show_channel_selector(void) void CanvasNoteEvent::hide_channel_selector(void) { - if(_channel_selector_widget) { + if (_channel_selector_widget) { _channel_selector_widget->hide(); delete _channel_selector_widget; _channel_selector_widget = 0; @@ -178,7 +183,7 @@ CanvasNoteEvent::on_event(GdkEvent* ev) d_velocity = 1; } - if(ev->scroll.direction == GDK_SCROLL_UP) { + if (ev->scroll.direction == GDK_SCROLL_UP) { _region.note_selected(this, true); if (_region.mouse_state() == MidiRegionView::SelectTouchDragging) { // TODO: absolute velocity @@ -186,7 +191,7 @@ CanvasNoteEvent::on_event(GdkEvent* ev) _region.change_velocity(d_velocity, true); } return true; - } else if(ev->scroll.direction == GDK_SCROLL_DOWN) { + } else if (ev->scroll.direction == GDK_SCROLL_DOWN) { _region.note_selected(this, true); if (_region.mouse_state() == MidiRegionView::SelectTouchDragging) { // TODO: absolute velocity @@ -221,7 +226,7 @@ CanvasNoteEvent::on_event(GdkEvent* ev) case GDK_LEAVE_NOTIFY: Keyboard::magic_widget_drop_focus(); - if(! selected()) { + if (! selected()) { hide_velocity(); } _region.get_canvas_group()->grab_focus(); @@ -305,7 +310,7 @@ CanvasNoteEvent::on_event(GdkEvent* ev) event_y = ev->button.y; _item->property_parent().get_value()->w2i(event_x, event_y); - if(ev->button.button == 3) { + if (ev->button.button == 3) { return true; } diff --git a/gtk2_ardour/midi_streamview.cc b/gtk2_ardour/midi_streamview.cc index 1dd33820d9..de14f302e5 100644 --- a/gtk2_ardour/midi_streamview.cc +++ b/gtk2_ardour/midi_streamview.cc @@ -473,18 +473,19 @@ MidiStreamView::update_rec_regions (boost::shared_ptr data, nframes_t tmp = iter; ++tmp; - + + boost::shared_ptr region = boost::dynamic_pointer_cast(iter->first); + if (!region || !iter->second) { + iter = tmp; + continue; + } + if (!canvas_item_visible (rec_rects[n].rectangle)) { /* rect already hidden, this region is done */ iter = tmp; continue; } - boost::shared_ptr region = boost::dynamic_pointer_cast(iter->first); - if (!region) { - continue; - } - nframes_t origlen = region->length(); if (region == rec_regions.back().first && rec_active) { diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index 6bcffb34d2..a05bc7278a 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -164,9 +164,9 @@ MidiModel::const_iterator::operator++() if (_is_end) throw std::logic_error("Attempt to iterate past end of MidiModel"); - cerr << "const_iterator::operator++: _event type:" << hex << "0x" << int(_event.type()) + /*cerr << "const_iterator::operator++: _event type:" << hex << "0x" << int(_event.type()) << " buffer: 0x" << int(_event.buffer()[0]) << " 0x" << int(_event.buffer()[1]) - << " 0x" << int(_event.buffer()[2]) << endl; + << " 0x" << int(_event.buffer()[2]) << endl;*/ if(! (_event.is_note() || _event.is_cc() || _event.is_pgm_change() || _event.is_pitch_bender() || _event.is_channel_aftertouch()) ) { cerr << "FAILED event buffer: " << hex << int(_event.buffer()[0]) << int(_event.buffer()[1]) << int(_event.buffer()[2]) << endl; @@ -186,7 +186,7 @@ MidiModel::const_iterator::operator++() if (ret) { //cerr << "Incremented " << _control_iter->automation_list->parameter().id() << " to " << x << endl; _control_iter->x = x; - _control_iter->x = y; + _control_iter->y = y; } else { //cerr << "Hit end of " << _control_iter->automation_list->parameter().id() << endl; _control_iter->automation_list.reset(); @@ -196,15 +196,17 @@ MidiModel::const_iterator::operator++() // Now find and point at the earliest event + + const std::vector::iterator old_control_iter = _control_iter; _control_iter = _control_iters.begin(); for (std::vector::iterator i = _control_iters.begin(); i != _control_iters.end(); ++i) { - if (i->x < _control_iter->x) { + if (i->x < _control_iter->x && i != old_control_iter) { _control_iter = i; } } - + enum Type { NIL, NOTE_ON, NOTE_OFF, AUTOMATION }; Type type = NIL;