X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_model.cc;h=ac3360ea2b0e77776f38a43ecfea767a56fae7bc;hb=56469c195640b561119852fd6d27a4b56e5af7e2;hp=e35c5c6d9838b89ae66f98cfce5df4a69391a580;hpb=bc56eb8bd73c7b456b646ba0cc627d449baa37f2;p=ardour.git diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index e35c5c6d98..ac3360ea2b 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -135,9 +135,7 @@ MidiModel::DeltaCommand::operator()() // 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); @@ -147,7 +145,7 @@ MidiModel::DeltaCommand::operator()() _model->remove_note_unlocked(*i); } - _model->write_unlock(); + lock.reset(); _model->ContentsChanged(); /* EMIT SIGNAL */ } @@ -157,9 +155,7 @@ MidiModel::DeltaCommand::undo() // 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); @@ -169,7 +165,7 @@ MidiModel::DeltaCommand::undo() _model->add_note_unlocked(*i); } - _model->write_unlock(); + lock.reset(); _model->ContentsChanged(); /* EMIT SIGNAL */ } @@ -271,7 +267,7 @@ MidiModel::DeltaCommand::set_state (const XMLNode& delta_command, int /*version* if (added_notes) { XMLNodeList notes = added_notes->children(); transform(notes.begin(), notes.end(), back_inserter(_added_notes), - sigc::mem_fun(*this, &DeltaCommand::unmarshal_note)); + boost::bind (&DeltaCommand::unmarshal_note, this, _1)); } _removed_notes.clear(); @@ -279,7 +275,7 @@ MidiModel::DeltaCommand::set_state (const XMLNode& delta_command, int /*version* if (removed_notes) { XMLNodeList notes = removed_notes->children(); transform(notes.begin(), notes.end(), back_inserter(_removed_notes), - sigc::mem_fun(*this, &DeltaCommand::unmarshal_note)); + boost::bind (&DeltaCommand::unmarshal_note, this, _1)); } return 0; @@ -292,14 +288,16 @@ MidiModel::DeltaCommand::get_state() delta_command->add_property("midi-source", _model->midi_source()->id().to_s()); XMLNode* added_notes = delta_command->add_child(ADDED_NOTES_ELEMENT); - for_each(_added_notes.begin(), _added_notes.end(), sigc::compose( - sigc::mem_fun(*added_notes, &XMLNode::add_child_nocopy), - sigc::mem_fun(*this, &DeltaCommand::marshal_note))); + for_each(_added_notes.begin(), _added_notes.end(), + boost::bind( + boost::bind (&XMLNode::add_child_nocopy, *added_notes, _1), + boost::bind (&DeltaCommand::marshal_note, this, _1))); XMLNode* removed_notes = delta_command->add_child(REMOVED_NOTES_ELEMENT); - for_each(_removed_notes.begin(), _removed_notes.end(), sigc::compose( - sigc::mem_fun(*removed_notes, &XMLNode::add_child_nocopy), - sigc::mem_fun(*this, &DeltaCommand::marshal_note))); + for_each(_removed_notes.begin(), _removed_notes.end(), + boost::bind ( + boost::bind (&XMLNode::add_child_nocopy, *removed_notes, _1), + boost::bind (&DeltaCommand::marshal_note, this, _1))); return *delta_command; } @@ -328,7 +326,7 @@ void MidiModel::DiffCommand::change(const boost::shared_ptr< Evoral::Note > note, Property prop, uint8_t new_value) { - NotePropertyChange change; + NoteChange change; change.note = note; change.property = prop; @@ -361,7 +359,7 @@ void MidiModel::DiffCommand::change(const boost::shared_ptr< Evoral::Note > note, Property prop, TimeType new_time) { - NotePropertyChange change; + NoteChange change; change.note = note; change.property = prop; @@ -387,9 +385,7 @@ MidiModel::DiffCommand::change(const boost::shared_ptr< Evoral::Note > 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; @@ -412,16 +408,14 @@ MidiModel::DiffCommand::operator()() } } - _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; @@ -444,12 +438,12 @@ MidiModel::DiffCommand::undo() } } - _model->write_unlock(); + lock.reset(); _model->ContentsChanged(); /* EMIT SIGNAL */ } XMLNode& -MidiModel::DiffCommand::marshal_change(const NotePropertyChange& change) +MidiModel::DiffCommand::marshal_change(const NoteChange& change) { XMLNode* xml_change = new XMLNode("change"); @@ -522,11 +516,11 @@ MidiModel::DiffCommand::marshal_change(const NotePropertyChange& change) return *xml_change; } -MidiModel::DiffCommand::NotePropertyChange +MidiModel::DiffCommand::NoteChange MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change) { XMLProperty* prop; - NotePropertyChange change; + NoteChange change; unsigned int note; unsigned int channel; unsigned int velocity; @@ -658,9 +652,9 @@ MidiModel::DiffCommand::set_state(const XMLNode& diff_command, int /*version*/) if (changed_notes) { XMLNodeList notes = changed_notes->children(); - transform (notes.begin(), notes.end(), back_inserter(_changes), - sigc::mem_fun(*this, &DiffCommand::unmarshal_change)); + boost::bind (&DiffCommand::unmarshal_change, this, _1)); + } return 0; @@ -673,9 +667,10 @@ MidiModel::DiffCommand::get_state () diff_command->add_property("midi-source", _model->midi_source()->id().to_s()); XMLNode* changes = diff_command->add_child(DIFF_NOTES_ELEMENT); - for_each(_changes.begin(), _changes.end(), sigc::compose( - sigc::mem_fun(*changes, &XMLNode::add_child_nocopy), - sigc::mem_fun(*this, &DiffCommand::marshal_change))); + for_each(_changes.begin(), _changes.end(), + boost::bind ( + boost::bind (&XMLNode::add_child_nocopy, *changes, _1), + boost::bind (&DiffCommand::marshal_change, this, _1))); return *diff_command; } @@ -690,20 +685,21 @@ MidiModel::DiffCommand::get_state () bool MidiModel::write_to(boost::shared_ptr 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::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; @@ -731,3 +727,24 @@ MidiModel::find_note (boost::shared_ptr > other) return boost::shared_ptr >(); } + +/** 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)); +}