various minor MIDI fixes: prevent duplicate note entry with mouse, show note info more often with verbose cursor, fix some crashes from click+move on notes ... lots more where this comes from

git-svn-id: svn://localhost/ardour2/branches/3.0@7128 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2010-05-20 22:38:12 +00:00
parent e58f6752af
commit a196405da9
9 changed files with 90 additions and 21 deletions

View file

@ -151,8 +151,9 @@ public:
void apply_command(Session& session, Command* cmd);
void apply_command_as_subcommand(Session& session, Command* cmd);
bool write_to(boost::shared_ptr<MidiSource> source, Evoral::MusicalTime begin = Evoral::MinMusicalTime,
Evoral::MusicalTime end = Evoral::MaxMusicalTime);
bool write_to(boost::shared_ptr<MidiSource> source);
bool write_section_to(boost::shared_ptr<MidiSource> source, Evoral::MusicalTime begin = Evoral::MinMusicalTime,
Evoral::MusicalTime end = Evoral::MaxMusicalTime);
// MidiModel doesn't use the normal AutomationList serialisation code
// since controller data is stored in the .mid

View file

@ -111,7 +111,7 @@ class MidiSource : virtual public Source
boost::shared_ptr<MidiModel> model() { return _model; }
void set_model(boost::shared_ptr<MidiModel> m) { _model = m; }
void drop_model() { _model.reset(); }
void drop_model();
protected:
virtual void flush_midi() = 0;

View file

@ -676,6 +676,36 @@ MidiModel::DiffCommand::get_state ()
return *diff_command;
}
/** Write all of the model to a MidiSource (i.e. save the model).
* This is different from manually using read to write to a source in that
* note off events are written regardless of the track mode. This is so the
* user can switch a recorded track (with note durations from some instrument)
* to percussive, save, reload, then switch it back to sustained without
* destroying the original note durations.
*/
bool
MidiModel::write_to (boost::shared_ptr<MidiSource> source)
{
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();
set_edited(false);
return true;
}
/** Write part or all of the model to a MidiSource (i.e. save the model).
* This is different from manually using read to write to a source in that
* note off events are written regardless of the track mode. This is so the
@ -684,7 +714,7 @@ MidiModel::DiffCommand::get_state ()
* destroying the original note durations.
*/
bool
MidiModel::write_to (boost::shared_ptr<MidiSource> source, Evoral::MusicalTime begin_time, Evoral::MusicalTime end_time)
MidiModel::write_section_to (boost::shared_ptr<MidiSource> source, Evoral::MusicalTime begin_time, Evoral::MusicalTime end_time)
{
ReadLock lock(read_lock());
MidiStateTracker mst;

View file

@ -250,7 +250,11 @@ MidiSource::clone (Evoral::MusicalTime begin, Evoral::MusicalTime end)
newsrc->set_timeline_position(_timeline_position);
if (_model) {
_model->write_to (newsrc, begin, end);
if (begin == Evoral::MinMusicalTime && end == Evoral::MaxMusicalTime) {
_model->write_to (newsrc);
} else {
_model->write_section_to (newsrc, begin, end);
}
} else {
error << string_compose (_("programming error: %1"), X_("no model for MidiSource during ::clone()"));
return boost::shared_ptr<MidiSource>();
@ -290,3 +294,9 @@ MidiSource::set_note_mode(NoteMode mode)
}
}
void
MidiSource::drop_model ()
{
cerr << name() << " drop model\n";
_model.reset();
}

View file

@ -202,7 +202,8 @@ public:
bool edited() const { return _edited; }
void set_edited(bool yn) { _edited = yn; }
void add_note_unlocked(const boost::shared_ptr< Note<Time> > note);
bool contains (const boost::shared_ptr< Note<Time> > ev) const;
bool add_note_unlocked(const boost::shared_ptr< Note<Time> > note);
void remove_note_unlocked(const boost::shared_ptr< const Note<Time> > note);
uint8_t lowest_note() const { return _lowest_note; }

View file

@ -730,12 +730,38 @@ Sequence<Time>::append_sysex_unlocked(const MIDIEvent<Time>& ev)
}
template<typename Time>
void
bool
Sequence<Time>::contains(const boost::shared_ptr< Note<Time> > note) const
{
ReadLock lock (read_lock());
for (typename Sequence<Time>::Notes::const_iterator i = note_lower_bound(note->time());
i != _notes.end() && (*i)->time() == note->time(); ++i) {
if (*i == note) {
cerr << "Existing note matches: " << *i << endl;
return true;
}
}
cerr << "No matching note for " << note << endl;
return false;
}
template<typename Time>
bool
Sequence<Time>::add_note_unlocked(const boost::shared_ptr< Note<Time> > note)
{
DUMP(format("%1% add note %2% @ %3%\n") % this % (int)note->note() % note->time());
for (typename Sequence<Time>::Notes::iterator i = note_lower_bound(note->time());
i != _notes.end() && (*i)->time() == note->time(); ++i) {
if (*i == note) {
return false;
}
}
_edited = true;
_notes.insert(note);
return true;
}
template<typename Time>