* fixed bug: crash because of invalidated iterator while removing midi notes from model

git-svn-id: svn://localhost/ardour2/branches/3.0@3253 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Hans Baier 2008-04-15 23:00:06 +00:00
parent 8b3d298f6b
commit c4bdcb82af
4 changed files with 31 additions and 12 deletions

View file

@ -914,7 +914,6 @@ MidiRegionView::note_dropped(CanvasMidiEvent* ev, double dt, uint8_t dnote)
Selection::iterator next = i; Selection::iterator next = i;
++next; ++next;
command_remove_note(*i);
const boost::shared_ptr<Note> copy(new Note(*(*i)->note().get())); const boost::shared_ptr<Note> copy(new Note(*(*i)->note().get()));
// we need to snap here again in nframes_t in order to be sample accurate // we need to snap here again in nframes_t in order to be sample accurate
@ -948,12 +947,12 @@ MidiRegionView::note_dropped(CanvasMidiEvent* ev, double dt, uint8_t dnote)
copy->set_note(new_pitch); copy->set_note(new_pitch);
command_remove_note(*i);
command_add_note(copy); command_add_note(copy);
_marked_for_selection.insert(copy); _marked_for_selection.insert(copy);
i = next; i = next;
} }
apply_command(); apply_command();
// care about notes being moved beyond the upper/lower bounds on the canvas // care about notes being moved beyond the upper/lower bounds on the canvas

View file

@ -83,7 +83,6 @@ public:
inline size_t n_notes() const { return _notes.size(); } inline size_t n_notes() const { return _notes.size(); }
inline bool empty() const { return _notes.size() == 0 && _controls.size() == 0; } inline bool empty() const { return _notes.size() == 0 && _controls.size() == 0; }
/* FIXME: use better data structure */
typedef std::vector< boost::shared_ptr<Note> > Notes; typedef std::vector< boost::shared_ptr<Note> > Notes;
inline static bool note_time_comparator (const boost::shared_ptr<const Note> a, inline static bool note_time_comparator (const boost::shared_ptr<const Note> a,
@ -188,8 +187,8 @@ public:
const_iterator begin() const { return const_iterator(*this, 0); } const_iterator begin() const { return const_iterator(*this, 0); }
const const_iterator& end() const { return _end_iter; } const const_iterator& end() const { return _end_iter; }
const MidiSource *midi_source() const { return _midi_source; } const MidiSource *midi_source() const;
void set_midi_source(MidiSource *source) { _midi_source = source; } void set_midi_source(MidiSource *source);
private: private:
friend class DeltaCommand; friend class DeltaCommand;

View file

@ -386,6 +386,8 @@ MidiModel::end_write(bool delete_stuck)
if ((*n)->duration() == 0) { if ((*n)->duration() == 0) {
cerr << "WARNING: Stuck note lost: " << (*n)->note() << endl; cerr << "WARNING: Stuck note lost: " << (*n)->note() << endl;
n = _notes.erase(n); n = _notes.erase(n);
// we have to break here because erase invalidates the iterator
break;
} else { } else {
++n; ++n;
} }
@ -521,11 +523,19 @@ MidiModel::remove_note_unlocked(const boost::shared_ptr<const Note> note)
{ {
//cerr << "MidiModel " << this << " remove note " << (int)note.note() << " @ " << note.time() << endl; //cerr << "MidiModel " << this << " remove note " << (int)note.note() << " @ " << note.time() << endl;
for(Notes::iterator n = _notes.begin(); n != _notes.end(); ++n) { for(Notes::iterator n = _notes.begin(); n != _notes.end(); ++n) {
if(**n == *note) { Note _n = *(*n);
Note _note =*note;
cerr << "======================================= " << endl;
cerr << int(_n.note()) << "@" << int(_n.time()) << "[" << int(_n.channel()) << "] --" << int(_n.duration()) << "-- #" << int(_n.velocity()) << endl;
cerr << int(_note.note()) << "@" << int(_note.time()) << "[" << int(_note.channel()) << "] --" << int(_note.duration()) << "-- #" << int(_note.velocity()) << endl;
cerr << "Equal: " << bool(_n == _note) << endl;
cerr << endl << endl;
if(_n == _note) {
_notes.erase(n); _notes.erase(n);
} // we have to break here, because erase invalidates all iterators, ie. n itself
break;
}
} }
} }
/** Slow! for debugging only. */ /** Slow! for debugging only. */
@ -840,3 +850,14 @@ MidiModel::get_state()
return *node; return *node;
} }
const MidiSource *
MidiModel::midi_source() const
{
return _midi_source;
}
void
MidiModel::set_midi_source(MidiSource *source)
{
_midi_source = source;
}

View file

@ -167,10 +167,10 @@ struct Event {
inline uint32_t& size() { return _size; } inline uint32_t& size() { return _size; }
inline uint8_t type() const { return (_buffer[0] & 0xF0); } inline uint8_t type() const { return (_buffer[0] & 0xF0); }
inline uint8_t channel() const { return (_buffer[0] & 0x0F); } inline uint8_t channel() const { return (_buffer[0] & 0x0F); }
inline void set_channel(uint8_t channel) { _buffer[0] = (0xF0 & _buffer[0]) | channel; } inline void set_channel(uint8_t channel) { _buffer[0] = (0xF0 & _buffer[0]) | (0x0F & channel); }
inline bool is_note_on() const { return (type() == MIDI_CMD_NOTE_ON); } inline bool is_note_on() const { return (type() == MIDI_CMD_NOTE_ON); }
inline bool is_note_off() const { return (type() == MIDI_CMD_NOTE_OFF); } inline bool is_note_off() const { return (type() == MIDI_CMD_NOTE_OFF); }
inline bool is_cc() const { return (type() == MIDI_CMD_CONTROL); } inline bool is_cc() const { return (type() == MIDI_CMD_CONTROL); }
inline bool is_note() const { return (is_note_on() || is_note_off()); } inline bool is_note() const { return (is_note_on() || is_note_off()); }
inline uint8_t note() const { return (_buffer[1]); } inline uint8_t note() const { return (_buffer[1]); }
inline uint8_t velocity() const { return (_buffer[2]); } inline uint8_t velocity() const { return (_buffer[2]); }