// This could be made much faster by using a priority_queue for added and
// removed notes (or sort here), and doing a single iteration over _model
- Glib::Mutex::Lock lm (_model->_midi_source->mutex());
- _model->_midi_source->invalidate(); // release model read lock
- _model->write_lock();
+ MidiModel::WriteLock lock(_model->edit_lock());
for (NoteList::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i) {
_model->add_note_unlocked(*i);
_model->remove_note_unlocked(*i);
}
- _model->write_unlock();
+ lock.reset();
_model->ContentsChanged(); /* EMIT SIGNAL */
}
// This could be made much faster by using a priority_queue for added and
// removed notes (or sort here), and doing a single iteration over _model
- Glib::Mutex::Lock lm (_model->_midi_source->mutex());
- _model->_midi_source->invalidate(); // release model read lock
- _model->write_lock();
+ MidiModel::WriteLock lock(_model->edit_lock());;
for (NoteList::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i) {
_model->remove_note_unlocked(*i);
_model->add_note_unlocked(*i);
}
- _model->write_unlock();
+ lock.reset();
_model->ContentsChanged(); /* EMIT SIGNAL */
}
#define DELTA_COMMAND_ELEMENT "DeltaCommand"
int
-MidiModel::DeltaCommand::set_state (const XMLNode& delta_command, int version)
+MidiModel::DeltaCommand::set_state (const XMLNode& delta_command, int /*version*/)
{
if (delta_command.name() != string(DELTA_COMMAND_ELEMENT)) {
return 1;
void
MidiModel::DiffCommand::operator()()
{
- Glib::Mutex::Lock lm (_model->_midi_source->mutex());
- _model->_midi_source->invalidate(); // release model read lock
- _model->write_lock();
+ MidiModel::WriteLock lock(_model->edit_lock());
for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
Property prop = i->property;
}
}
- _model->write_unlock();
+ lock.reset();
_model->ContentsChanged(); /* EMIT SIGNAL */
}
void
MidiModel::DiffCommand::undo()
{
- Glib::Mutex::Lock lm (_model->_midi_source->mutex());
- _model->_midi_source->invalidate(); // release model read lock
- _model->write_lock();
+ MidiModel::WriteLock lock(_model->edit_lock());
for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
Property prop = i->property;
}
}
- _model->write_unlock();
+ lock.reset();
_model->ContentsChanged(); /* EMIT SIGNAL */
}
}
int
-MidiModel::DiffCommand::set_state(const XMLNode& diff_command, int version)
+MidiModel::DiffCommand::set_state(const XMLNode& diff_command, int /*version*/)
{
if (diff_command.name() != string(DIFF_COMMAND_ELEMENT)) {
return 1;
bool
MidiModel::write_to(boost::shared_ptr<MidiSource> source)
{
- read_lock();
+ ReadLock lock(read_lock());
const bool old_percussive = percussive();
set_percussive(false);
source->drop_model();
+ source->mark_streaming_midi_write_started(note_mode(), _midi_source->timeline_position());
for (Evoral::Sequence<TimeType>::const_iterator i = begin(); i != end(); ++i) {
source->append_event_unlocked_beats(*i);
}
set_percussive(old_percussive);
+ source->mark_streaming_write_completed();
- read_unlock();
set_edited(false);
return true;
boost::shared_ptr<Evoral::Note<MidiModel::TimeType> >
MidiModel::find_note (boost::shared_ptr<Evoral::Note<TimeType> > other)
{
- for (Notes::iterator l = notes().lower_bound(other); (*l)->time() == other->time(); ++l) {
- if (*l == other) {
- return *l;
+ Notes::iterator l = notes().lower_bound(other);
+
+ if (l != notes().end()) {
+ for (; (*l)->time() == other->time(); ++l) {
+ if (*l == other) {
+ return *l;
+ }
}
}
+
return boost::shared_ptr<Evoral::Note<TimeType> >();
}
+
+/** Lock and invalidate the source.
+ * This should be used by commands and editing things
+ */
+MidiModel::WriteLock
+MidiModel::edit_lock()
+{
+ Glib::Mutex::Lock* source_lock = new Glib::Mutex::Lock(_midi_source->mutex());
+ _midi_source->invalidate(); // Release cached iterator's read lock on model
+ return WriteLock(new WriteLockImpl(source_lock, _lock, _control_lock));
+}
+
+/** Lock just the model, the source lock must already be held.
+ * This should only be called from libardour/evoral places
+ */
+MidiModel::WriteLock
+MidiModel::write_lock()
+{
+ assert(!_midi_source->mutex().trylock());
+ return WriteLock(new WriteLockImpl(NULL, _lock, _control_lock));
+}