Fix lost MIDI note offs and controllers.
[ardour.git] / libs / ardour / midi_model.cc
1 /*
2   Copyright (C) 2007 Paul Davis
3   Author: David Robillard
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #include <algorithm>
22 #include <iostream>
23 #include <set>
24 #include <stdexcept>
25 #include <stdint.h>
26
27 #include "pbd/compose.h"
28 #include "pbd/enumwriter.h"
29 #include "pbd/error.h"
30
31 #include "evoral/Control.hpp"
32
33 #include "midi++/events.h"
34
35 #include "ardour/automation_control.h"
36 #include "ardour/midi_automation_list_binder.h"
37 #include "ardour/midi_model.h"
38 #include "ardour/midi_source.h"
39 #include "ardour/midi_state_tracker.h"
40 #include "ardour/session.h"
41 #include "ardour/types.h"
42
43 #include "i18n.h"
44
45 using namespace std;
46 using namespace ARDOUR;
47 using namespace PBD;
48
49 MidiModel::MidiModel (boost::shared_ptr<MidiSource> s)
50         : AutomatableSequence<TimeType>(s->session())
51 {
52         set_midi_source (s);
53 }
54
55 /** Start a new NoteDiff command.
56  *
57  * This has no side-effects on the model or Session, the returned command
58  * can be held on to for as long as the caller wishes, or discarded without
59  * formality, until apply_command is called and ownership is taken.
60  */
61 MidiModel::NoteDiffCommand*
62 MidiModel::new_note_diff_command (const string name)
63 {
64         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
65         assert (ms);
66
67         return new NoteDiffCommand (ms->model(), name);
68 }
69
70 /** Start a new SysExDiff command */
71 MidiModel::SysExDiffCommand*
72 MidiModel::new_sysex_diff_command (const string name)
73 {
74         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
75         assert (ms);
76
77         return new SysExDiffCommand (ms->model(), name);
78 }
79
80 /** Start a new PatchChangeDiff command */
81 MidiModel::PatchChangeDiffCommand*
82 MidiModel::new_patch_change_diff_command (const string name)
83 {
84         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
85         assert (ms);
86
87         return new PatchChangeDiffCommand (ms->model(), name);
88 }
89
90
91 /** Apply a command.
92  *
93  * Ownership of cmd is taken, it must not be deleted by the caller.
94  * The command will constitute one item on the undo stack.
95  */
96 void
97 MidiModel::apply_command(Session& session, Command* cmd)
98 {
99         session.begin_reversible_command(cmd->name());
100         (*cmd)();
101         session.commit_reversible_command(cmd);
102         set_edited(true);
103 }
104
105 /** Apply a command as part of a larger reversible transaction
106  *
107  * Ownership of cmd is taken, it must not be deleted by the caller.
108  * The command will constitute one item on the undo stack.
109  */
110 void
111 MidiModel::apply_command_as_subcommand(Session& session, Command* cmd)
112 {
113         (*cmd)();
114         session.add_command(cmd);
115         set_edited(true);
116 }
117
118 /************** DIFF COMMAND ********************/
119
120 #define NOTE_DIFF_COMMAND_ELEMENT "NoteDiffCommand"
121 #define DIFF_NOTES_ELEMENT "ChangedNotes"
122 #define ADDED_NOTES_ELEMENT "AddedNotes"
123 #define REMOVED_NOTES_ELEMENT "RemovedNotes"
124 #define SIDE_EFFECT_REMOVALS_ELEMENT "SideEffectRemovals"
125 #define SYSEX_DIFF_COMMAND_ELEMENT "SysExDiffCommand"
126 #define DIFF_SYSEXES_ELEMENT "ChangedSysExes"
127 #define PATCH_CHANGE_DIFF_COMMAND_ELEMENT "PatchChangeDiffCommand"
128 #define ADDED_PATCH_CHANGES_ELEMENT "AddedPatchChanges"
129 #define REMOVED_PATCH_CHANGES_ELEMENT "RemovedPatchChanges"
130 #define DIFF_PATCH_CHANGES_ELEMENT "ChangedPatchChanges"
131
132 MidiModel::DiffCommand::DiffCommand(boost::shared_ptr<MidiModel> m, const std::string& name)
133         : Command (name)
134         , _model (m)
135         , _name (name)
136 {
137         assert(_model);
138 }
139
140 MidiModel::NoteDiffCommand::NoteDiffCommand (boost::shared_ptr<MidiModel> m, const XMLNode& node)
141         : DiffCommand (m, "")
142 {
143         assert (_model);
144         set_state (node, Stateful::loading_state_version);
145 }
146
147 void
148 MidiModel::NoteDiffCommand::add (const NotePtr note)
149 {
150         _removed_notes.remove(note);
151         _added_notes.push_back(note);
152 }
153
154 void
155 MidiModel::NoteDiffCommand::remove (const NotePtr note)
156 {
157         _added_notes.remove(note);
158         _removed_notes.push_back(note);
159 }
160
161 void
162 MidiModel::NoteDiffCommand::side_effect_remove (const NotePtr note)
163 {
164         side_effect_removals.insert (note);
165 }
166
167 void
168 MidiModel::NoteDiffCommand::change (const NotePtr note, Property prop,
169                                     uint8_t new_value)
170 {
171         assert (note);
172
173         NoteChange change;
174
175         switch (prop) {
176         case NoteNumber:
177                 if (new_value == note->note()) {
178                         return;
179                 }
180                 change.old_value = note->note();
181                 break;
182         case Velocity:
183                 if (new_value == note->velocity()) {
184                         return;
185                 }
186                 change.old_value = note->velocity();
187                 break;
188         case Channel:
189                 if (new_value == note->channel()) {
190                         return;
191                 }
192                 change.old_value = note->channel();
193                 break;
194
195
196         case StartTime:
197                 fatal << "MidiModel::DiffCommand::change() with integer argument called for start time" << endmsg;
198                 abort(); /*NOTREACHED*/
199                 break;
200         case Length:
201                 fatal << "MidiModel::DiffCommand::change() with integer argument called for length" << endmsg;
202                 abort(); /*NOTREACHED*/
203                 break;
204         }
205
206         change.note = note;
207         change.property = prop;
208         change.new_value = new_value;
209
210         _changes.push_back (change);
211 }
212
213 void
214 MidiModel::NoteDiffCommand::change (const NotePtr note, Property prop,
215                                     TimeType new_time)
216 {
217         assert (note);
218
219         NoteChange change;
220
221         switch (prop) {
222         case NoteNumber:
223         case Channel:
224         case Velocity:
225                 fatal << "MidiModel::NoteDiffCommand::change() with time argument called for note, channel or velocity" << endmsg;
226                 break;
227
228         case StartTime:
229                 if (Evoral::musical_time_equal (note->time(), new_time)) {
230                         return;
231                 }
232                 change.old_time = note->time();
233                 break;
234         case Length:
235                 if (Evoral::musical_time_equal (note->length(), new_time)) {
236                         return;
237                 }
238                 change.old_time = note->length();
239                 break;
240         }
241
242         change.note = note;
243         change.property = prop;
244         change.new_time = new_time;
245
246         _changes.push_back (change);
247 }
248
249 MidiModel::NoteDiffCommand &
250 MidiModel::NoteDiffCommand::operator+= (const NoteDiffCommand& other)
251 {
252         if (this == &other) {
253                 return *this;
254         }
255
256         if (_model != other._model) {
257                 return *this;
258         }
259
260         _added_notes.insert (_added_notes.end(), other._added_notes.begin(), other._added_notes.end());
261         _removed_notes.insert (_removed_notes.end(), other._removed_notes.begin(), other._removed_notes.end());
262         side_effect_removals.insert (other.side_effect_removals.begin(), other.side_effect_removals.end());
263         _changes.insert (_changes.end(), other._changes.begin(), other._changes.end());
264
265         return *this;
266 }
267
268 void
269 MidiModel::NoteDiffCommand::operator() ()
270 {
271         {
272                 MidiModel::WriteLock lock(_model->edit_lock());
273
274                 for (NoteList::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i) {
275                         if (!_model->add_note_unlocked(*i)) {
276                                 /* failed to add it, so don't leave it in the removed list, to
277                                    avoid apparent errors on undo.
278                                 */
279                                 _removed_notes.remove (*i);
280                         }
281                 }
282
283                 for (NoteList::iterator i = _removed_notes.begin(); i != _removed_notes.end(); ++i) {
284                         _model->remove_note_unlocked(*i);
285                 }
286
287                 /* notes we modify in a way that requires remove-then-add to maintain ordering */
288                 set<NotePtr> temporary_removals;
289
290                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
291                         Property prop = i->property;
292
293                         if (!i->note) {
294                                 /* note found during deserialization, so try
295                                    again now that the model state is different.
296                                 */
297                                 i->note = _model->find_note (i->note_id);
298                                 assert (i->note);
299                         }
300
301                         switch (prop) {
302                         case NoteNumber:
303                                 if (temporary_removals.find (i->note) == temporary_removals.end()) {
304                                         _model->remove_note_unlocked (i->note);
305                                         temporary_removals.insert (i->note);
306                                 }
307                                 i->note->set_note (i->new_value);
308                                 break;
309
310                         case StartTime:
311                                 if (temporary_removals.find (i->note) == temporary_removals.end()) {
312                                         _model->remove_note_unlocked (i->note);
313                                         temporary_removals.insert (i->note);
314                                 }
315                                 i->note->set_time (i->new_time);
316                                 break;
317
318                         case Channel:
319                                 if (temporary_removals.find (i->note) == temporary_removals.end()) {
320                                         _model->remove_note_unlocked (i->note);
321                                         temporary_removals.insert (i->note);
322                                 }
323                                 i->note->set_channel (i->new_value);
324                                 break;
325
326                                 /* no remove-then-add required for these properties, since we do not index them
327                                  */
328
329                         case Velocity:
330                                 i->note->set_velocity (i->new_value);
331                                 break;
332
333                         case Length:
334                                 i->note->set_length (i->new_time);
335                                 break;
336
337                         }
338                 }
339
340                 for (set<NotePtr>::iterator i = temporary_removals.begin(); i != temporary_removals.end(); ++i) {
341                         NoteDiffCommand side_effects (model(), "side effects");
342                         if (_model->add_note_unlocked (*i, &side_effects)) {
343                                 /* The note was re-added ok */
344                                 *this += side_effects;
345                         } else {
346                                 /* The note that we removed earlier could not be re-added.  This change record
347                                    must say that the note was removed.  We'll keep the changes we made, though,
348                                    as if the note is re-added by the undo the changes must also be undone.
349                                 */
350                                 _removed_notes.push_back (*i);
351                         }
352                 }
353                 
354                 if (!side_effect_removals.empty()) {
355                         cerr << "SER: \n";
356                         for (set<NotePtr>::iterator i = side_effect_removals.begin(); i != side_effect_removals.end(); ++i) {
357                                 cerr << "\t" << *i << ' ' << **i << endl;
358                         }
359                 }
360         }
361
362         _model->ContentsChanged(); /* EMIT SIGNAL */
363 }
364
365 void
366 MidiModel::NoteDiffCommand::undo ()
367 {
368         {
369                 MidiModel::WriteLock lock(_model->edit_lock());
370
371                 for (NoteList::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i) {
372                         _model->remove_note_unlocked(*i);
373                 }
374
375                 /* Apply changes first; this is important in the case of a note change which
376                    resulted in the note being removed by the overlap checker.  If the overlap
377                    checker removes a note, it will be in _removed_notes.  We are going to re-add
378                    it below, but first we must undo the changes we made so that the overlap
379                    checker doesn't refuse the re-add.
380                 */
381
382                 /* notes we modify in a way that requires remove-then-add to maintain ordering */
383                 set<NotePtr> temporary_removals;
384
385
386                 /* lazily discover any affected notes that were not discovered when
387                  * loading the history because of deletions, etc.
388                  */
389
390                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
391                         if (!i->note) {
392                                 i->note = _model->find_note (i->note_id);
393                                 assert (i->note);
394                         }
395                 }
396                                 
397                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
398                         Property prop = i->property;
399
400                         switch (prop) {
401                         case NoteNumber:
402                                 if (temporary_removals.find (i->note) == temporary_removals.end() &&
403                                     find (_removed_notes.begin(), _removed_notes.end(), i->note) == _removed_notes.end()) {
404
405                                         /* We only need to mark this note for re-add if (a) we haven't
406                                            already marked it and (b) it isn't on the _removed_notes
407                                            list (which means that it has already been removed and it
408                                            will be re-added anyway)
409                                         */
410
411                                         _model->remove_note_unlocked (i->note);
412                                         temporary_removals.insert (i->note);
413                                 }
414                                 i->note->set_note (i->old_value);
415                                 break;
416
417                         case StartTime:
418                                 if (temporary_removals.find (i->note) == temporary_removals.end() &&
419                                     find (_removed_notes.begin(), _removed_notes.end(), i->note) == _removed_notes.end()) {
420
421                                         /* See above ... */
422
423                                         _model->remove_note_unlocked (i->note);
424                                         temporary_removals.insert (i->note);
425                                 }
426                                 i->note->set_time (i->old_time);
427                                 break;
428
429                         case Channel:
430                                 if (temporary_removals.find (i->note) == temporary_removals.end() &&
431                                     find (_removed_notes.begin(), _removed_notes.end(), i->note) == _removed_notes.end()) {
432
433                                         /* See above ... */
434
435                                         _model->remove_note_unlocked (i->note);
436                                         temporary_removals.insert (i->note);
437                                 }
438                                 i->note->set_channel (i->old_value);
439                                 break;
440
441                                 /* no remove-then-add required for these properties, since we do not index them
442                                  */
443
444                         case Velocity:
445                                 i->note->set_velocity (i->old_value);
446                                 break;
447
448                         case Length:
449                                 i->note->set_length (i->old_time);
450                                 break;
451                         }
452                 }
453
454                 for (NoteList::iterator i = _removed_notes.begin(); i != _removed_notes.end(); ++i) {
455                         _model->add_note_unlocked(*i);
456                 }
457
458                 for (set<NotePtr>::iterator i = temporary_removals.begin(); i != temporary_removals.end(); ++i) {
459                         _model->add_note_unlocked (*i);
460                 }
461
462                 /* finally add back notes that were removed by the "do". we don't care
463                    about side effects here since the model should be back to its original
464                    state once this is done.
465                 */
466
467                 for (set<NotePtr>::iterator i = side_effect_removals.begin(); i != side_effect_removals.end(); ++i) {
468                         _model->add_note_unlocked (*i);
469                 }
470         }
471         
472         _model->ContentsChanged(); /* EMIT SIGNAL */
473 }
474
475 XMLNode&
476 MidiModel::NoteDiffCommand::marshal_note(const NotePtr note)
477 {
478         XMLNode* xml_note = new XMLNode("note");
479
480         {
481                 ostringstream id_str(ios::ate);
482                 id_str << int(note->id());
483                 xml_note->add_property("id", id_str.str());
484         }
485
486         {
487                 ostringstream note_str(ios::ate);
488                 note_str << int(note->note());
489                 xml_note->add_property("note", note_str.str());
490         }
491
492         {
493                 ostringstream channel_str(ios::ate);
494                 channel_str << int(note->channel());
495                 xml_note->add_property("channel", channel_str.str());
496         }
497
498         {
499                 ostringstream time_str(ios::ate);
500                 time_str << note->time();
501                 xml_note->add_property("time", time_str.str());
502         }
503
504         {
505                 ostringstream length_str(ios::ate);
506                 length_str << note->length();
507                 xml_note->add_property("length", length_str.str());
508         }
509
510         {
511                 ostringstream velocity_str(ios::ate);
512                 velocity_str << (unsigned int) note->velocity();
513                 xml_note->add_property("velocity", velocity_str.str());
514         }
515
516         return *xml_note;
517 }
518
519 Evoral::Sequence<MidiModel::TimeType>::NotePtr
520 MidiModel::NoteDiffCommand::unmarshal_note (XMLNode *xml_note)
521 {
522         unsigned int note;
523         XMLProperty* prop;
524         unsigned int channel;
525         MidiModel::TimeType time;
526         MidiModel::TimeType length;
527         unsigned int velocity;
528         gint id;
529
530         if ((prop = xml_note->property("id")) != 0) {
531                 istringstream id_str(prop->value());
532                 id_str >> id;
533         } else {
534                 error << "note information missing ID value" << endmsg;
535                 id = -1;
536         }
537
538         if ((prop = xml_note->property("note")) != 0) {
539                 istringstream note_str(prop->value());
540                 note_str >> note;
541         } else {
542                 warning << "note information missing note value" << endmsg;
543                 note = 127;
544         }
545
546         if ((prop = xml_note->property("channel")) != 0) {
547                 istringstream channel_str(prop->value());
548                 channel_str >> channel;
549         } else {
550                 warning << "note information missing channel" << endmsg;
551                 channel = 0;
552         }
553
554         if ((prop = xml_note->property("time")) != 0) {
555                 istringstream time_str(prop->value());
556                 time_str >> time;
557         } else {
558                 warning << "note information missing time" << endmsg;
559                 time = 0;
560         }
561
562         if ((prop = xml_note->property("length")) != 0) {
563                 istringstream length_str(prop->value());
564                 length_str >> length;
565         } else {
566                 warning << "note information missing length" << endmsg;
567                 length = 1;
568         }
569
570         if ((prop = xml_note->property("velocity")) != 0) {
571                 istringstream velocity_str(prop->value());
572                 velocity_str >> velocity;
573         } else {
574                 warning << "note information missing velocity" << endmsg;
575                 velocity = 127;
576         }
577
578         NotePtr note_ptr(new Evoral::Note<TimeType>(channel, time, length, note, velocity));
579         note_ptr->set_id (id);
580
581         return note_ptr;
582 }
583
584 XMLNode&
585 MidiModel::NoteDiffCommand::marshal_change (const NoteChange& change)
586 {
587         XMLNode* xml_change = new XMLNode("Change");
588
589         /* first, the change itself */
590
591         xml_change->add_property ("property", enum_2_string (change.property));
592
593         {
594                 ostringstream old_value_str (ios::ate);
595                 if (change.property == StartTime || change.property == Length) {
596                         old_value_str << change.old_time;
597                 } else {
598                         old_value_str << (unsigned int) change.old_value;
599                 }
600                 xml_change->add_property ("old", old_value_str.str());
601         }
602
603         {
604                 ostringstream new_value_str (ios::ate);
605                 if (change.property == StartTime || change.property == Length) {
606                         new_value_str << change.new_time;
607                 } else {
608                         new_value_str << (unsigned int) change.new_value;
609                 }
610                 xml_change->add_property ("new", new_value_str.str());
611         }
612
613         ostringstream id_str;
614         id_str << change.note->id();
615         xml_change->add_property ("id", id_str.str());
616
617         return *xml_change;
618 }
619
620 MidiModel::NoteDiffCommand::NoteChange
621 MidiModel::NoteDiffCommand::unmarshal_change (XMLNode *xml_change)
622 {
623         XMLProperty* prop;
624         NoteChange change;
625
626         if ((prop = xml_change->property("property")) != 0) {
627                 change.property = (Property) string_2_enum (prop->value(), change.property);
628         } else {
629                 fatal << "!!!" << endmsg;
630                 abort(); /*NOTREACHED*/
631         }
632
633         if ((prop = xml_change->property ("id")) == 0) {
634                 error << _("No NoteID found for note property change - ignored") << endmsg;
635                 return change;
636         }
637
638         gint note_id = atoi (prop->value().c_str());
639
640         if ((prop = xml_change->property ("old")) != 0) {
641                 istringstream old_str (prop->value());
642                 if (change.property == StartTime || change.property == Length) {
643                         old_str >> change.old_time;
644                 } else {
645                         int integer_value_so_that_istream_does_the_right_thing;
646                         old_str >> integer_value_so_that_istream_does_the_right_thing;
647                         change.old_value = integer_value_so_that_istream_does_the_right_thing;
648                 }
649         } else {
650                 fatal << "!!!" << endmsg;
651                 abort(); /*NOTREACHED*/
652         }
653
654         if ((prop = xml_change->property ("new")) != 0) {
655                 istringstream new_str (prop->value());
656                 if (change.property == StartTime || change.property == Length) {
657                         new_str >> change.new_time;
658                 } else {
659                         int integer_value_so_that_istream_does_the_right_thing;
660                         new_str >> integer_value_so_that_istream_does_the_right_thing;
661                         change.new_value = integer_value_so_that_istream_does_the_right_thing;
662                 }
663         } else {
664                 fatal << "!!!" << endmsg;
665                 abort(); /*NOTREACHED*/
666         }
667
668         /* we must point at the instance of the note that is actually in the model.
669            so go look for it ... it may not be there (it could have been
670            deleted in a later operation, so store the note id so that we can
671            look it up again later).
672         */
673
674         change.note = _model->find_note (note_id);
675         change.note_id = note_id;
676
677         return change;
678 }
679
680 int
681 MidiModel::NoteDiffCommand::set_state (const XMLNode& diff_command, int /*version*/)
682 {
683         if (diff_command.name() != string (NOTE_DIFF_COMMAND_ELEMENT)) {
684                 return 1;
685         }
686
687         /* additions */
688
689         _added_notes.clear();
690         XMLNode* added_notes = diff_command.child(ADDED_NOTES_ELEMENT);
691         if (added_notes) {
692                 XMLNodeList notes = added_notes->children();
693                 transform(notes.begin(), notes.end(), back_inserter(_added_notes),
694                           boost::bind (&NoteDiffCommand::unmarshal_note, this, _1));
695         }
696
697
698         /* removals */
699
700         _removed_notes.clear();
701         XMLNode* removed_notes = diff_command.child(REMOVED_NOTES_ELEMENT);
702         if (removed_notes) {
703                 XMLNodeList notes = removed_notes->children();
704                 transform(notes.begin(), notes.end(), back_inserter(_removed_notes),
705                           boost::bind (&NoteDiffCommand::unmarshal_note, this, _1));
706         }
707
708
709         /* changes */
710
711         _changes.clear();
712
713         XMLNode* changed_notes = diff_command.child(DIFF_NOTES_ELEMENT);
714
715         if (changed_notes) {
716                 XMLNodeList notes = changed_notes->children();
717                 transform (notes.begin(), notes.end(), back_inserter(_changes),
718                            boost::bind (&NoteDiffCommand::unmarshal_change, this, _1));
719
720         }
721
722         /* side effect removals caused by changes */
723
724         side_effect_removals.clear();
725
726         XMLNode* side_effect_notes = diff_command.child(SIDE_EFFECT_REMOVALS_ELEMENT);
727
728         if (side_effect_notes) {
729                 XMLNodeList notes = side_effect_notes->children();
730                 for (XMLNodeList::iterator n = notes.begin(); n != notes.end(); ++n) {
731                         side_effect_removals.insert (unmarshal_note (*n));
732                 }
733         }
734
735         return 0;
736 }
737
738 XMLNode&
739 MidiModel::NoteDiffCommand::get_state ()
740 {
741         XMLNode* diff_command = new XMLNode (NOTE_DIFF_COMMAND_ELEMENT);
742         diff_command->add_property("midi-source", _model->midi_source()->id().to_s());
743
744         XMLNode* changes = diff_command->add_child(DIFF_NOTES_ELEMENT);
745         for_each(_changes.begin(), _changes.end(),
746                  boost::bind (
747                          boost::bind (&XMLNode::add_child_nocopy, changes, _1),
748                          boost::bind (&NoteDiffCommand::marshal_change, this, _1)));
749
750         XMLNode* added_notes = diff_command->add_child(ADDED_NOTES_ELEMENT);
751         for_each(_added_notes.begin(), _added_notes.end(),
752                  boost::bind(
753                          boost::bind (&XMLNode::add_child_nocopy, added_notes, _1),
754                          boost::bind (&NoteDiffCommand::marshal_note, this, _1)));
755
756         XMLNode* removed_notes = diff_command->add_child(REMOVED_NOTES_ELEMENT);
757         for_each(_removed_notes.begin(), _removed_notes.end(),
758                  boost::bind (
759                          boost::bind (&XMLNode::add_child_nocopy, removed_notes, _1),
760                          boost::bind (&NoteDiffCommand::marshal_note, this, _1)));
761
762         /* if this command had side-effects, store that state too
763          */
764
765         if (!side_effect_removals.empty()) {
766                 XMLNode* side_effect_notes = diff_command->add_child(SIDE_EFFECT_REMOVALS_ELEMENT);
767                 for_each(side_effect_removals.begin(), side_effect_removals.end(),
768                          boost::bind (
769                                  boost::bind (&XMLNode::add_child_nocopy, side_effect_notes, _1),
770                                  boost::bind (&NoteDiffCommand::marshal_note, this, _1)));
771         }
772
773         return *diff_command;
774 }
775
776 MidiModel::SysExDiffCommand::SysExDiffCommand (boost::shared_ptr<MidiModel> m, const XMLNode& node)
777         : DiffCommand (m, "")
778 {
779         assert (_model);
780         set_state (node, Stateful::loading_state_version);
781 }
782
783 void
784 MidiModel::SysExDiffCommand::change (boost::shared_ptr<Evoral::Event<TimeType> > s, TimeType new_time)
785 {
786         Change change;
787
788         change.sysex = s;
789         change.property = Time;
790         change.old_time = s->time ();
791         change.new_time = new_time;
792
793         _changes.push_back (change);
794 }
795
796 void
797 MidiModel::SysExDiffCommand::operator() ()
798 {
799         {
800                 MidiModel::WriteLock lock (_model->edit_lock ());
801
802                 for (list<SysExPtr>::iterator i = _removed.begin(); i != _removed.end(); ++i) {
803                         _model->remove_sysex_unlocked (*i);
804                 }
805
806                 /* find any sysex events that were missing when unmarshalling */
807
808                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
809                         if (!i->sysex) {
810                                 i->sysex = _model->find_sysex (i->sysex_id);
811                                 assert (i->sysex);
812                         }
813                 }
814
815                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
816                         switch (i->property) {
817                         case Time:
818                                 i->sysex->set_time (i->new_time);
819                         }
820                 }
821         }
822
823         _model->ContentsChanged (); /* EMIT SIGNAL */
824 }
825
826 void
827 MidiModel::SysExDiffCommand::undo ()
828 {
829         {
830                 MidiModel::WriteLock lock (_model->edit_lock ());
831
832                 for (list<SysExPtr>::iterator i = _removed.begin(); i != _removed.end(); ++i) {
833                         _model->add_sysex_unlocked (*i);
834                 }
835
836                 /* find any sysex events that were missing when unmarshalling */
837
838                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
839                         if (!i->sysex) {
840                                 i->sysex = _model->find_sysex (i->sysex_id);
841                                 assert (i->sysex);
842                         }
843                 }
844
845                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
846                         switch (i->property) {
847                         case Time:
848                                 i->sysex->set_time (i->old_time);
849                                 break;
850                         }
851                 }
852
853         }
854
855         _model->ContentsChanged(); /* EMIT SIGNAL */
856 }
857
858 void
859 MidiModel::SysExDiffCommand::remove (SysExPtr sysex)
860 {
861         _removed.push_back(sysex);
862 }
863
864 XMLNode&
865 MidiModel::SysExDiffCommand::marshal_change (const Change& change)
866 {
867         XMLNode* xml_change = new XMLNode ("Change");
868
869         /* first, the change itself */
870
871         xml_change->add_property ("property", enum_2_string (change.property));
872
873         {
874                 ostringstream old_value_str (ios::ate);
875                 old_value_str << change.old_time;
876                 xml_change->add_property ("old", old_value_str.str());
877         }
878
879         {
880                 ostringstream new_value_str (ios::ate);
881                 new_value_str << change.new_time;
882                 xml_change->add_property ("new", new_value_str.str());
883         }
884
885         ostringstream id_str;
886         id_str << change.sysex->id();
887         xml_change->add_property ("id", id_str.str());
888
889         return *xml_change;
890 }
891
892 MidiModel::SysExDiffCommand::Change
893 MidiModel::SysExDiffCommand::unmarshal_change (XMLNode *xml_change)
894 {
895         XMLProperty* prop;
896         Change change;
897
898         if ((prop = xml_change->property ("property")) != 0) {
899                 change.property = (Property) string_2_enum (prop->value(), change.property);
900         } else {
901                 fatal << "!!!" << endmsg;
902                 abort(); /*NOTREACHED*/
903         }
904
905         if ((prop = xml_change->property ("id")) == 0) {
906                 error << _("No SysExID found for sys-ex property change - ignored") << endmsg;
907                 return change;
908         }
909
910         gint sysex_id = atoi (prop->value().c_str());
911
912         if ((prop = xml_change->property ("old")) != 0) {
913                 istringstream old_str (prop->value());
914                 old_str >> change.old_time;
915         } else {
916                 fatal << "!!!" << endmsg;
917                 abort(); /*NOTREACHED*/
918         }
919
920         if ((prop = xml_change->property ("new")) != 0) {
921                 istringstream new_str (prop->value());
922                 new_str >> change.new_time;
923         } else {
924                 fatal << "!!!" << endmsg;
925                 abort(); /*NOTREACHED*/
926         }
927
928         /* we must point at the instance of the sysex that is actually in the model.
929            so go look for it ...
930         */
931
932         change.sysex = _model->find_sysex (sysex_id);
933         change.sysex_id = sysex_id;
934
935         return change;
936 }
937
938 int
939 MidiModel::SysExDiffCommand::set_state (const XMLNode& diff_command, int /*version*/)
940 {
941         if (diff_command.name() != string (SYSEX_DIFF_COMMAND_ELEMENT)) {
942                 return 1;
943         }
944
945         /* changes */
946
947         _changes.clear();
948
949         XMLNode* changed_sysexes = diff_command.child (DIFF_SYSEXES_ELEMENT);
950
951         if (changed_sysexes) {
952                 XMLNodeList sysexes = changed_sysexes->children();
953                 transform (sysexes.begin(), sysexes.end(), back_inserter (_changes),
954                            boost::bind (&SysExDiffCommand::unmarshal_change, this, _1));
955
956         }
957
958         return 0;
959 }
960
961 XMLNode&
962 MidiModel::SysExDiffCommand::get_state ()
963 {
964         XMLNode* diff_command = new XMLNode (SYSEX_DIFF_COMMAND_ELEMENT);
965         diff_command->add_property ("midi-source", _model->midi_source()->id().to_s());
966
967         XMLNode* changes = diff_command->add_child(DIFF_SYSEXES_ELEMENT);
968         for_each (_changes.begin(), _changes.end(),
969                   boost::bind (
970                           boost::bind (&XMLNode::add_child_nocopy, changes, _1),
971                           boost::bind (&SysExDiffCommand::marshal_change, this, _1)));
972
973         return *diff_command;
974 }
975
976 MidiModel::PatchChangeDiffCommand::PatchChangeDiffCommand (boost::shared_ptr<MidiModel> m, const string& name)
977         : DiffCommand (m, name)
978 {
979         assert (_model);
980 }
981
982 MidiModel::PatchChangeDiffCommand::PatchChangeDiffCommand (boost::shared_ptr<MidiModel> m, const XMLNode & node)
983         : DiffCommand (m, "")
984 {
985         assert (_model);
986         set_state (node, Stateful::loading_state_version);
987 }
988
989 void
990 MidiModel::PatchChangeDiffCommand::add (PatchChangePtr p)
991 {
992         _added.push_back (p);
993 }
994
995 void
996 MidiModel::PatchChangeDiffCommand::remove (PatchChangePtr p)
997 {
998         _removed.push_back (p);
999 }
1000
1001 void
1002 MidiModel::PatchChangeDiffCommand::change_time (PatchChangePtr patch, TimeType t)
1003 {
1004         Change c;
1005         c.property = Time;
1006         c.patch = patch;
1007         c.old_time = patch->time ();
1008         c.new_time = t;
1009
1010         _changes.push_back (c);
1011 }
1012
1013 void
1014 MidiModel::PatchChangeDiffCommand::change_channel (PatchChangePtr patch, uint8_t channel)
1015 {
1016         Change c;
1017         c.property = Channel;
1018         c.patch = patch;
1019         c.old_channel = patch->channel ();
1020         c.new_channel = channel;
1021         c.patch_id = patch->id();
1022
1023         _changes.push_back (c);
1024 }
1025
1026 void
1027 MidiModel::PatchChangeDiffCommand::change_program (PatchChangePtr patch, uint8_t program)
1028 {
1029         Change c;
1030         c.property = Program;
1031         c.patch = patch;
1032         c.old_program = patch->program ();
1033         c.new_program = program;
1034         c.patch_id = patch->id();
1035
1036         _changes.push_back (c);
1037 }
1038
1039 void
1040 MidiModel::PatchChangeDiffCommand::change_bank (PatchChangePtr patch, int bank)
1041 {
1042         Change c;
1043         c.property = Bank;
1044         c.patch = patch;
1045         c.old_bank = patch->bank ();
1046         c.new_bank = bank;
1047
1048         _changes.push_back (c);
1049 }
1050
1051 void
1052 MidiModel::PatchChangeDiffCommand::operator() ()
1053 {
1054         {
1055                 MidiModel::WriteLock lock (_model->edit_lock ());
1056
1057                 for (list<PatchChangePtr>::iterator i = _added.begin(); i != _added.end(); ++i) {
1058                         _model->add_patch_change_unlocked (*i);
1059                 }
1060
1061                 for (list<PatchChangePtr>::iterator i = _removed.begin(); i != _removed.end(); ++i) {
1062                         _model->remove_patch_change_unlocked (*i);
1063                 }
1064
1065                 /* find any patch change events that were missing when unmarshalling */
1066
1067                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
1068                         if (!i->patch) {
1069                                 i->patch = _model->find_patch_change (i->patch_id);
1070                                 assert (i->patch);
1071                         }
1072                 }
1073
1074                 set<PatchChangePtr> temporary_removals;
1075
1076                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
1077                         switch (i->property) {
1078                         case Time:
1079                                 if (temporary_removals.find (i->patch) == temporary_removals.end()) {
1080                                         _model->remove_patch_change_unlocked (i->patch);
1081                                         temporary_removals.insert (i->patch);
1082                                 }
1083                                 i->patch->set_time (i->new_time);
1084                                 break;
1085
1086                         case Channel:
1087                                 i->patch->set_channel (i->new_channel);
1088                                 break;
1089
1090                         case Program:
1091                                 i->patch->set_program (i->new_program);
1092                                 break;
1093
1094                         case Bank:
1095                                 i->patch->set_bank (i->new_bank);
1096                                 break;
1097                         }
1098                 }
1099
1100                 for (set<PatchChangePtr>::iterator i = temporary_removals.begin(); i != temporary_removals.end(); ++i) {
1101                         _model->add_patch_change_unlocked (*i);
1102                 }
1103         }
1104
1105         _model->ContentsChanged (); /* EMIT SIGNAL */
1106 }
1107
1108 void
1109 MidiModel::PatchChangeDiffCommand::undo ()
1110 {
1111         {
1112                 MidiModel::WriteLock lock (_model->edit_lock());
1113
1114                 for (list<PatchChangePtr>::iterator i = _added.begin(); i != _added.end(); ++i) {
1115                         _model->remove_patch_change_unlocked (*i);
1116                 }
1117
1118                 for (list<PatchChangePtr>::iterator i = _removed.begin(); i != _removed.end(); ++i) {
1119                         _model->add_patch_change_unlocked (*i);
1120                 }
1121
1122                 /* find any patch change events that were missing when unmarshalling */
1123
1124                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
1125                         if (!i->patch) {
1126                                 i->patch = _model->find_patch_change (i->patch_id);
1127                                 assert (i->patch);
1128                         }
1129                 }
1130
1131                 set<PatchChangePtr> temporary_removals;
1132
1133                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
1134                         switch (i->property) {
1135                         case Time:
1136                                 if (temporary_removals.find (i->patch) == temporary_removals.end()) {
1137                                         _model->remove_patch_change_unlocked (i->patch);
1138                                         temporary_removals.insert (i->patch);
1139                                 }
1140                                 i->patch->set_time (i->old_time);
1141                                 break;
1142
1143                         case Channel:
1144                                 i->patch->set_channel (i->old_channel);
1145                                 break;
1146
1147                         case Program:
1148                                 i->patch->set_program (i->old_program);
1149                                 break;
1150
1151                         case Bank:
1152                                 i->patch->set_bank (i->old_bank);
1153                                 break;
1154                         }
1155                 }
1156
1157                 for (set<PatchChangePtr>::iterator i = temporary_removals.begin(); i != temporary_removals.end(); ++i) {
1158                         _model->add_patch_change_unlocked (*i);
1159                 }
1160
1161         }
1162
1163         _model->ContentsChanged (); /* EMIT SIGNAL */
1164 }
1165
1166 XMLNode &
1167 MidiModel::PatchChangeDiffCommand::marshal_patch_change (constPatchChangePtr p)
1168 {
1169         XMLNode* n = new XMLNode ("patch-change");
1170
1171         {
1172                 ostringstream s (ios::ate);
1173                 s << int (p->id ());
1174                 n->add_property ("id", s.str());
1175         }
1176
1177         {
1178                 ostringstream s (ios::ate);
1179                 s << p->time ();
1180                 n->add_property ("time", s.str ());
1181         }
1182
1183         {
1184                 ostringstream s (ios::ate);
1185                 s << int (p->channel ());
1186                 n->add_property ("channel", s.str ());
1187         }
1188
1189         {
1190                 ostringstream s (ios::ate);
1191                 s << int (p->program ());
1192                 n->add_property ("program", s.str ());
1193         }
1194
1195         {
1196                 ostringstream s (ios::ate);
1197                 s << int (p->bank ());
1198                 n->add_property ("bank", s.str ());
1199         }
1200
1201         return *n;
1202 }
1203
1204 XMLNode&
1205 MidiModel::PatchChangeDiffCommand::marshal_change (const Change& c)
1206 {
1207         XMLNode* n = new XMLNode (X_("Change"));
1208
1209         n->add_property (X_("property"), enum_2_string (c.property));
1210
1211         {
1212                 ostringstream s (ios::ate);
1213                 if (c.property == Time) {
1214                         s << c.old_time;
1215                 } else if (c.property == Channel) {
1216                         s << c.old_channel;
1217                 } else if (c.property == Program) {
1218                         s << int (c.old_program);
1219                 } else if (c.property == Bank) {
1220                         s << c.old_bank;
1221                 }
1222
1223                 n->add_property (X_("old"), s.str ());
1224         }
1225
1226         {
1227                 ostringstream s (ios::ate);
1228
1229                 if (c.property == Time) {
1230                         s << c.new_time;
1231                 } else if (c.property == Channel) {
1232                         s << c.new_channel;
1233                 } else if (c.property == Program) {
1234                         s << int (c.new_program);
1235                 } else if (c.property == Bank) {
1236                         s << c.new_bank;
1237                 }
1238
1239                 n->add_property (X_("new"), s.str ());
1240         }
1241
1242         {
1243                 ostringstream s;
1244                 s << c.patch->id ();
1245                 n->add_property ("id", s.str ());
1246         }
1247
1248         return *n;
1249 }
1250
1251 MidiModel::PatchChangePtr
1252 MidiModel::PatchChangeDiffCommand::unmarshal_patch_change (XMLNode* n)
1253 {
1254         XMLProperty* prop;
1255         Evoral::event_id_t id = 0;
1256         Evoral::MusicalTime time = 0;
1257         int channel = 0;
1258         int program = 0;
1259         int bank = 0;
1260         
1261         if ((prop = n->property ("id")) != 0) {
1262                 istringstream s (prop->value());
1263                 s >> id;
1264         }
1265
1266         if ((prop = n->property ("time")) != 0) {
1267                 istringstream s (prop->value ());
1268                 s >> time;
1269         }
1270
1271         if ((prop = n->property ("channel")) != 0) {
1272                 istringstream s (prop->value ());
1273                 s >> channel;
1274         }
1275
1276         if ((prop = n->property ("program")) != 0) {
1277                 istringstream s (prop->value ());
1278                 s >> program;
1279         }
1280
1281         if ((prop = n->property ("bank")) != 0) {
1282                 istringstream s (prop->value ());
1283                 s >> bank;
1284         }
1285
1286         PatchChangePtr p (new Evoral::PatchChange<TimeType> (time, channel, program, bank));
1287         assert(id);
1288         p->set_id (id);
1289         return p;
1290 }
1291
1292 MidiModel::PatchChangeDiffCommand::Change
1293 MidiModel::PatchChangeDiffCommand::unmarshal_change (XMLNode* n)
1294 {
1295         XMLProperty* prop;
1296         Change c;
1297         int an_int;
1298
1299         prop = n->property ("property");
1300         assert (prop);
1301         c.property = (Property) string_2_enum (prop->value(), c.property);
1302
1303         prop = n->property ("id");
1304         assert (prop);
1305         Evoral::event_id_t const id = atoi (prop->value().c_str());
1306
1307         /* we need to load via an int intermediate for all properties that are 
1308            actually uint8_t (char/byte).
1309         */
1310
1311         prop = n->property ("old");
1312         assert (prop);
1313         {
1314                 istringstream s (prop->value ());
1315                 if (c.property == Time) {
1316                         s >> c.old_time;
1317                 } else if (c.property == Channel) {
1318                         s >> an_int;
1319                         c.old_channel = an_int;
1320                 } else if (c.property == Program) {
1321                         s >> an_int;
1322                         c.old_program = an_int;
1323                 } else if (c.property == Bank) {
1324                         s >> an_int;
1325                         c.old_bank = an_int;
1326                 }
1327         }
1328
1329         prop = n->property ("new");
1330         assert (prop);
1331         {
1332                 istringstream s (prop->value ());
1333
1334                 if (c.property == Time) {
1335                         s >> c.new_time;
1336                 } else if (c.property == Channel) {
1337                         s >> an_int;
1338                         c.new_channel = an_int;
1339                 } else if (c.property == Program) {
1340                         s >> an_int;
1341                         c.new_program = an_int;
1342                 } else if (c.property == Bank) {
1343                         s >> an_int;
1344                         c.new_bank = an_int;
1345                 }
1346         }
1347
1348         c.patch = _model->find_patch_change (id);
1349         c.patch_id = id;
1350
1351         return c;
1352 }
1353
1354 int
1355 MidiModel::PatchChangeDiffCommand::set_state (const XMLNode& diff_command, int /*version*/)
1356 {
1357         if (diff_command.name() != PATCH_CHANGE_DIFF_COMMAND_ELEMENT) {
1358                 return 1;
1359         }
1360
1361         _added.clear ();
1362         XMLNode* added = diff_command.child (ADDED_PATCH_CHANGES_ELEMENT);
1363         if (added) {
1364                 XMLNodeList p = added->children ();
1365                 transform (p.begin(), p.end(), back_inserter (_added), boost::bind (&PatchChangeDiffCommand::unmarshal_patch_change, this, _1));
1366         }
1367
1368         _removed.clear ();
1369         XMLNode* removed = diff_command.child (REMOVED_PATCH_CHANGES_ELEMENT);
1370         if (removed) {
1371                 XMLNodeList p = removed->children ();
1372                 transform (p.begin(), p.end(), back_inserter (_removed), boost::bind (&PatchChangeDiffCommand::unmarshal_patch_change, this, _1));
1373         }
1374
1375         _changes.clear ();
1376         XMLNode* changed = diff_command.child (DIFF_PATCH_CHANGES_ELEMENT);
1377         if (changed) {
1378                 XMLNodeList p = changed->children ();
1379                 transform (p.begin(), p.end(), back_inserter (_changes), boost::bind (&PatchChangeDiffCommand::unmarshal_change, this, _1));
1380         }
1381
1382         return 0;
1383 }
1384
1385 XMLNode &
1386 MidiModel::PatchChangeDiffCommand::get_state ()
1387 {
1388         XMLNode* diff_command = new XMLNode (PATCH_CHANGE_DIFF_COMMAND_ELEMENT);
1389         diff_command->add_property("midi-source", _model->midi_source()->id().to_s());
1390
1391         XMLNode* added = diff_command->add_child (ADDED_PATCH_CHANGES_ELEMENT);
1392         for_each (_added.begin(), _added.end(),
1393                   boost::bind (
1394                           boost::bind (&XMLNode::add_child_nocopy, added, _1),
1395                           boost::bind (&PatchChangeDiffCommand::marshal_patch_change, this, _1)
1396                           )
1397                 );
1398
1399         XMLNode* removed = diff_command->add_child (REMOVED_PATCH_CHANGES_ELEMENT);
1400         for_each (_removed.begin(), _removed.end(),
1401                   boost::bind (
1402                           boost::bind (&XMLNode::add_child_nocopy, removed, _1),
1403                           boost::bind (&PatchChangeDiffCommand::marshal_patch_change, this, _1)
1404                           )
1405                 );
1406
1407         XMLNode* changes = diff_command->add_child (DIFF_PATCH_CHANGES_ELEMENT);
1408         for_each (_changes.begin(), _changes.end(),
1409                   boost::bind (
1410                           boost::bind (&XMLNode::add_child_nocopy, changes, _1),
1411                           boost::bind (&PatchChangeDiffCommand::marshal_change, this, _1)
1412                           )
1413                 );
1414
1415         return *diff_command;
1416 }
1417
1418 /** Write all of the model to a MidiSource (i.e. save the model).
1419  * This is different from manually using read to write to a source in that
1420  * note off events are written regardless of the track mode.  This is so the
1421  * user can switch a recorded track (with note durations from some instrument)
1422  * to percussive, save, reload, then switch it back to sustained without
1423  * destroying the original note durations.
1424  *
1425  * Similarly, control events are written without interpolation (as with the
1426  * `Discrete' mode).
1427  */
1428 bool
1429 MidiModel::write_to (boost::shared_ptr<MidiSource> source)
1430 {
1431         ReadLock lock(read_lock());
1432
1433         const bool old_percussive = percussive();
1434         set_percussive(false);
1435
1436         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1437         assert (ms);
1438
1439         source->drop_model();
1440         source->mark_streaming_midi_write_started (note_mode());
1441
1442         for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
1443                 source->append_event_unlocked_beats(*i);
1444         }
1445
1446         set_percussive(old_percussive);
1447         source->mark_streaming_write_completed();
1448
1449         set_edited(false);
1450
1451         return true;
1452 }
1453
1454 /** very similar to ::write_to() but writes to the model's own
1455     existing midi_source, without making it call MidiSource::drop_model().
1456     the caller is a MidiSource that needs to catch up with the state
1457     of the model.
1458 */
1459 bool
1460 MidiModel::sync_to_source ()
1461 {
1462         ReadLock lock(read_lock());
1463
1464         const bool old_percussive = percussive();
1465         set_percussive(false);
1466
1467         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1468         assert (ms);
1469
1470         ms->mark_streaming_midi_write_started (note_mode());
1471
1472         for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
1473                 ms->append_event_unlocked_beats(*i);
1474         }
1475
1476         set_percussive (old_percussive);
1477         ms->mark_streaming_write_completed ();
1478
1479         set_edited (false);
1480
1481         return true;
1482 }
1483
1484 /** Write part or all of the model to a MidiSource (i.e. save the model).
1485  * This is different from manually using read to write to a source in that
1486  * note off events are written regardless of the track mode.  This is so the
1487  * user can switch a recorded track (with note durations from some instrument)
1488  * to percussive, save, reload, then switch it back to sustained without
1489  * destroying the original note durations.
1490  */
1491 bool
1492 MidiModel::write_section_to (boost::shared_ptr<MidiSource> source, Evoral::MusicalTime begin_time, Evoral::MusicalTime end_time)
1493 {
1494         ReadLock lock(read_lock());
1495         MidiStateTracker mst;
1496
1497         const bool old_percussive = percussive();
1498         set_percussive(false);
1499
1500         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1501         assert (ms);
1502
1503         source->drop_model();
1504         source->mark_streaming_midi_write_started (note_mode());
1505
1506         for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
1507                 const Evoral::Event<Evoral::MusicalTime>& ev (*i);
1508
1509                 if (ev.time() >= begin_time && ev.time() < end_time) {
1510
1511                         const Evoral::MIDIEvent<Evoral::MusicalTime>* mev =
1512                                 static_cast<const Evoral::MIDIEvent<Evoral::MusicalTime>* > (&ev);
1513
1514                         if (!mev) {
1515                                 continue;
1516                         }
1517
1518
1519                         if (mev->is_note_off()) {
1520
1521                                 if (!mst.active (mev->note(), mev->channel())) {
1522                                         /* the matching note-on was outside the
1523                                            time range we were given, so just
1524                                            ignore this note-off.
1525                                         */
1526                                         continue;
1527                                 }
1528
1529                                 source->append_event_unlocked_beats (*i);
1530                                 mst.remove (mev->note(), mev->channel());
1531
1532                         } else if (mev->is_note_on()) {
1533                                 mst.add (mev->note(), mev->channel());
1534                                 source->append_event_unlocked_beats(*i);
1535                         } else {
1536                                 source->append_event_unlocked_beats(*i);
1537                         }
1538                 }
1539         }
1540
1541         mst.resolve_notes (*source, end_time);
1542
1543         set_percussive(old_percussive);
1544         source->mark_streaming_write_completed();
1545
1546         set_edited(false);
1547
1548         return true;
1549 }
1550
1551 XMLNode&
1552 MidiModel::get_state()
1553 {
1554         XMLNode *node = new XMLNode("MidiModel");
1555         return *node;
1556 }
1557
1558 Evoral::Sequence<MidiModel::TimeType>::NotePtr
1559 MidiModel::find_note (NotePtr other)
1560 {
1561         Notes::iterator l = notes().lower_bound(other);
1562
1563         if (l != notes().end()) {
1564                 for (; (*l)->time() == other->time(); ++l) {
1565                         /* NB: compare note contents, not note pointers.
1566                            If "other" was a ptr to a note already in
1567                            the model, we wouldn't be looking for it,
1568                            would we now?
1569                         */
1570                         if (**l == *other) {
1571                                 return *l;
1572                         }
1573                 }
1574         }
1575
1576         return NotePtr();
1577 }
1578
1579 Evoral::Sequence<MidiModel::TimeType>::NotePtr
1580 MidiModel::find_note (gint note_id)
1581 {
1582         /* used only for looking up notes when reloading history from disk,
1583            so we don't care about performance *too* much.
1584         */
1585
1586         for (Notes::iterator l = notes().begin(); l != notes().end(); ++l) {
1587                 if ((*l)->id() == note_id) {
1588                         return *l;
1589                 }
1590         }
1591
1592         return NotePtr();
1593 }
1594
1595 MidiModel::PatchChangePtr
1596 MidiModel::find_patch_change (Evoral::event_id_t id)
1597 {
1598         for (PatchChanges::iterator i = patch_changes().begin(); i != patch_changes().end(); ++i) {
1599                 if ((*i)->id() == id) {
1600                         return *i;
1601                 }
1602         }
1603
1604         return PatchChangePtr ();
1605 }
1606
1607 boost::shared_ptr<Evoral::Event<MidiModel::TimeType> >
1608 MidiModel::find_sysex (gint sysex_id)
1609 {
1610         /* used only for looking up notes when reloading history from disk,
1611            so we don't care about performance *too* much.
1612         */
1613
1614         for (SysExes::iterator l = sysexes().begin(); l != sysexes().end(); ++l) {
1615                 if ((*l)->id() == sysex_id) {
1616                         return *l;
1617                 }
1618         }
1619
1620         return boost::shared_ptr<Evoral::Event<TimeType> > ();
1621 }
1622
1623 /** Lock and invalidate the source.
1624  * This should be used by commands and editing things
1625  */
1626 MidiModel::WriteLock
1627 MidiModel::edit_lock()
1628 {
1629         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1630         assert (ms);
1631
1632         Glib::Threads::Mutex::Lock* source_lock = new Glib::Threads::Mutex::Lock (ms->mutex());
1633         ms->invalidate(); // Release cached iterator's read lock on model
1634         return WriteLock(new WriteLockImpl(source_lock, _lock, _control_lock));
1635 }
1636
1637 /** Lock just the model, the source lock must already be held.
1638  * This should only be called from libardour/evoral places
1639  */
1640 MidiModel::WriteLock
1641 MidiModel::write_lock()
1642 {
1643         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1644         assert (ms);
1645
1646         assert (!ms->mutex().trylock ());
1647         return WriteLock(new WriteLockImpl(0, _lock, _control_lock));
1648 }
1649
1650 int
1651 MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg)
1652 {
1653         using namespace Evoral;
1654
1655         if (_writing || insert_merge_policy() == InsertMergeRelax) {
1656                 return 0;
1657         }
1658
1659         NoteDiffCommand* cmd = static_cast<NoteDiffCommand*>(arg);
1660
1661         TimeType sa = note->time();
1662         TimeType ea  = note->end_time();
1663
1664         const Pitches& p (pitches (note->channel()));
1665         NotePtr search_note(new Note<TimeType>(0, 0, 0, note->note()));
1666         set<NotePtr> to_be_deleted;
1667         bool set_note_length = false;
1668         bool set_note_time = false;
1669         TimeType note_time = note->time();
1670         TimeType note_length = note->length();
1671
1672         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 checking overlaps for note %2 @ %3\n", this, (int)note->note(), note->time()));
1673
1674         for (Pitches::const_iterator i = p.lower_bound (search_note);
1675              i != p.end() && (*i)->note() == note->note(); ++i) {
1676
1677                 TimeType sb = (*i)->time();
1678                 TimeType eb = (*i)->end_time();
1679                 OverlapType overlap = OverlapNone;
1680
1681                 if ((sb > sa) && (eb <= ea)) {
1682                         overlap = OverlapInternal;
1683                 } else if ((eb >= sa) && (eb <= ea)) {
1684                         overlap = OverlapStart;
1685                 } else if ((sb > sa) && (sb <= ea)) {
1686                         overlap = OverlapEnd;
1687                 } else if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
1688                         overlap = OverlapExternal;
1689                 } else {
1690                         /* no overlap */
1691                         continue;
1692                 }
1693
1694                 DEBUG_TRACE (DEBUG::Sequence, string_compose (
1695                                      "\toverlap is %1 for (%2,%3) vs (%4,%5)\n",
1696                                      enum_2_string(overlap), sa, ea, sb, eb));
1697
1698                 if (insert_merge_policy() == InsertMergeReject) {
1699                         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 just reject\n", this));
1700                         return -1;
1701                 }
1702
1703                 switch (overlap) {
1704                 case OverlapStart:
1705                         cerr << "OverlapStart\n";
1706                         /* existing note covers start of new note */
1707                         switch (insert_merge_policy()) {
1708                         case InsertMergeReplace:
1709                                 to_be_deleted.insert (*i);
1710                                 break;
1711                         case InsertMergeTruncateExisting:
1712                                 if (cmd) {
1713                                         cmd->change (*i, NoteDiffCommand::Length, (note->time() - (*i)->time()));
1714                                 }
1715                                 (*i)->set_length (note->time() - (*i)->time());
1716                                 break;
1717                         case InsertMergeTruncateAddition:
1718                                 set_note_time = true;
1719                                 set_note_length = true;
1720                                 note_time = (*i)->time() + (*i)->length();
1721                                 note_length = min (note_length, (*i)->length() - ((*i)->end_time() - note->time()));
1722                                 break;
1723                         case InsertMergeExtend:
1724                                 if (cmd) {
1725                                         cmd->change ((*i), NoteDiffCommand::Length, note->end_time() - (*i)->time());
1726                                 }
1727                                 (*i)->set_length (note->end_time() - (*i)->time());
1728                                 return -1; /* do not add the new note */
1729                                 break;
1730                         default:
1731                                 abort(); /*NOTREACHED*/
1732                                 /* stupid gcc */
1733                                 break;
1734                         }
1735                         break;
1736
1737                 case OverlapEnd:
1738                         cerr << "OverlapEnd\n";
1739                         /* existing note covers end of new note */
1740                         switch (insert_merge_policy()) {
1741                         case InsertMergeReplace:
1742                                 to_be_deleted.insert (*i);
1743                                 break;
1744
1745                         case InsertMergeTruncateExisting:
1746                                 /* resetting the start time of the existing note
1747                                    is a problem because of time ordering.
1748                                 */
1749                                 break;
1750
1751                         case InsertMergeTruncateAddition:
1752                                 set_note_length = true;
1753                                 note_length = min (note_length, ((*i)->time() - note->time()));
1754                                 break;
1755
1756                         case InsertMergeExtend:
1757                                 /* we can't reset the time of the existing note because
1758                                    that will corrupt time ordering. So remove the
1759                                    existing note and change the position/length
1760                                    of the new note (which has not been added yet)
1761                                 */
1762                                 to_be_deleted.insert (*i);
1763                                 set_note_length = true;
1764                                 note_length = min (note_length, (*i)->end_time() - note->time());
1765                                 break;
1766                         default:
1767                                 abort(); /*NOTREACHED*/
1768                                 /* stupid gcc */
1769                                 break;
1770                         }
1771                         break;
1772
1773                 case OverlapExternal:
1774                         cerr << "OverlapExt\n";
1775                         /* existing note overlaps all the new note */
1776                         switch (insert_merge_policy()) {
1777                         case InsertMergeReplace:
1778                                 to_be_deleted.insert (*i);
1779                                 break;
1780                         case InsertMergeTruncateExisting:
1781                         case InsertMergeTruncateAddition:
1782                         case InsertMergeExtend:
1783                                 /* cannot add in this case */
1784                                 return -1;
1785                         default:
1786                                 abort(); /*NOTREACHED*/
1787                                 /* stupid gcc */
1788                                 break;
1789                         }
1790                         break;
1791
1792                 case OverlapInternal:
1793                         cerr << "OverlapInt\n";
1794                         /* new note fully overlaps an existing note */
1795                         switch (insert_merge_policy()) {
1796                         case InsertMergeReplace:
1797                         case InsertMergeTruncateExisting:
1798                         case InsertMergeTruncateAddition:
1799                         case InsertMergeExtend:
1800                                 /* delete the existing note, the new one will cover it */
1801                                 to_be_deleted.insert (*i);
1802                                 break;
1803                         default:
1804                                 abort(); /*NOTREACHED*/
1805                                 /* stupid gcc */
1806                                 break;
1807                         }
1808                         break;
1809
1810                 default:
1811                         abort(); /*NOTREACHED*/
1812                         /* stupid gcc */
1813                         break;
1814                 }
1815         }
1816
1817         for (set<NotePtr>::iterator i = to_be_deleted.begin(); i != to_be_deleted.end(); ++i) {
1818                 remove_note_unlocked (*i);
1819
1820                 if (cmd) {
1821                         cmd->side_effect_remove (*i);
1822                 }
1823         }
1824
1825         if (set_note_time) {
1826                 if (cmd) {
1827                         cmd->change (note, NoteDiffCommand::StartTime, note_time);
1828                 }
1829                 note->set_time (note_time);
1830         }
1831
1832         if (set_note_length) {
1833                 if (cmd) {
1834                         cmd->change (note, NoteDiffCommand::Length, note_length);
1835                 }
1836                 note->set_length (note_length);
1837         }
1838
1839         return 0;
1840 }
1841
1842 InsertMergePolicy
1843 MidiModel::insert_merge_policy () const
1844 {
1845         /* XXX ultimately this should be a per-track or even per-model policy */
1846         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1847         assert (ms);
1848
1849         return ms->session().config.get_insert_merge_policy ();
1850 }
1851
1852 void
1853 MidiModel::set_midi_source (boost::shared_ptr<MidiSource> s)
1854 {
1855         boost::shared_ptr<MidiSource> old = _midi_source.lock ();
1856
1857         if (old) {
1858                 old->invalidate ();
1859         }
1860
1861         _midi_source_connections.drop_connections ();
1862
1863         _midi_source = s;
1864
1865         s->InterpolationChanged.connect_same_thread (
1866                 _midi_source_connections, boost::bind (&MidiModel::source_interpolation_changed, this, _1, _2)
1867                 );
1868
1869         s->AutomationStateChanged.connect_same_thread (
1870                 _midi_source_connections, boost::bind (&MidiModel::source_automation_state_changed, this, _1, _2)
1871                 );
1872 }
1873
1874 /** The source has signalled that the interpolation style for a parameter has changed.  In order to
1875  *  keep MidiSource and ControlList interpolation state the same, we pass this change onto the
1876  *  appropriate ControlList.
1877  *
1878  *  The idea is that MidiSource and the MidiModel's ControlList states are kept in sync, and one
1879  *  or the other is listened to by the GUI.
1880  */
1881 void
1882 MidiModel::source_interpolation_changed (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
1883 {
1884         Glib::Threads::Mutex::Lock lm (_control_lock);
1885         control(p)->list()->set_interpolation (s);
1886 }
1887
1888 /** A ControlList has signalled that its interpolation style has changed.  Again, in order to keep
1889  *  MidiSource and ControlList interpolation state in sync, we pass this change onto our MidiSource.
1890  */
1891 void
1892 MidiModel::control_list_interpolation_changed (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
1893 {
1894         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1895         assert (ms);
1896
1897         ms->set_interpolation_of (p, s);
1898 }
1899
1900 void
1901 MidiModel::source_automation_state_changed (Evoral::Parameter p, AutoState s)
1902 {
1903         Glib::Threads::Mutex::Lock lm (_control_lock);
1904         boost::shared_ptr<AutomationList> al = boost::dynamic_pointer_cast<AutomationList> (control(p)->list ());
1905         al->set_automation_state (s);
1906 }
1907
1908 void
1909 MidiModel::automation_list_automation_state_changed (Evoral::Parameter p, AutoState s)
1910 {
1911         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1912         assert (ms);
1913         ms->set_automation_state_of (p, s);
1914 }
1915
1916 boost::shared_ptr<Evoral::Control>
1917 MidiModel::control_factory (Evoral::Parameter const & p)
1918 {
1919         boost::shared_ptr<Evoral::Control> c = Automatable::control_factory (p);
1920
1921         /* Set up newly created control's lists to the appropriate interpolation and
1922            automation state from our source.
1923         */
1924
1925         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1926         assert (ms);
1927
1928         c->list()->set_interpolation (ms->interpolation_of (p));
1929
1930         boost::shared_ptr<AutomationList> al = boost::dynamic_pointer_cast<AutomationList> (c->list ());
1931         assert (al);
1932
1933         al->set_automation_state (ms->automation_state_of (p));
1934
1935         return c;
1936 }
1937
1938 boost::shared_ptr<const MidiSource>
1939 MidiModel::midi_source ()
1940 {
1941         return _midi_source.lock ();
1942 }
1943
1944 /** Moves notes, patch changes, controllers and sys-ex to insert silence at the start of the model.
1945  *  Adds commands to the session's current undo stack to reflect the movements.
1946  */
1947 void
1948 MidiModel::insert_silence_at_start (TimeType t)
1949 {
1950         boost::shared_ptr<MidiSource> s = _midi_source.lock ();
1951         assert (s);
1952
1953         /* Notes */
1954
1955         if (!notes().empty ()) {
1956                 NoteDiffCommand* c = new_note_diff_command ("insert silence");
1957
1958                 for (Notes::const_iterator i = notes().begin(); i != notes().end(); ++i) {
1959                         c->change (*i, NoteDiffCommand::StartTime, (*i)->time() + t);
1960                 }
1961
1962                 apply_command_as_subcommand (s->session(), c);
1963         }
1964
1965         /* Patch changes */
1966
1967         if (!patch_changes().empty ()) {
1968                 PatchChangeDiffCommand* c = new_patch_change_diff_command ("insert silence");
1969
1970                 for (PatchChanges::const_iterator i = patch_changes().begin(); i != patch_changes().end(); ++i) {
1971                         c->change_time (*i, (*i)->time() + t);
1972                 }
1973
1974                 apply_command_as_subcommand (s->session(), c);
1975         }
1976
1977         /* Controllers */
1978
1979         for (Controls::iterator i = controls().begin(); i != controls().end(); ++i) {
1980                 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (i->second);
1981                 XMLNode& before = ac->alist()->get_state ();
1982                 i->second->list()->shift (0, t);
1983                 XMLNode& after = ac->alist()->get_state ();
1984                 s->session().add_command (new MementoCommand<AutomationList> (new MidiAutomationListBinder (s, i->first), &before, &after));
1985         }
1986
1987         /* Sys-ex */
1988
1989         if (!sysexes().empty()) {
1990                 SysExDiffCommand* c = new_sysex_diff_command ("insert silence");
1991
1992                 for (SysExes::iterator i = sysexes().begin(); i != sysexes().end(); ++i) {
1993                         c->change (*i, (*i)->time() + t);
1994                 }
1995
1996                 apply_command_as_subcommand (s->session(), c);
1997         }
1998 }
1999
2000 /** Transpose notes in a time range by a given number of semitones.  Notes
2001  *  will be clamped at 0 and 127 if the transposition would make them exceed
2002  *  that range.
2003  *
2004  *  @param from Start time.
2005  *  @param end End time.
2006  *  @param semitones Number of semitones to transpose by (+ve is higher, -ve is lower).
2007  */
2008 void
2009 MidiModel::transpose (TimeType from, TimeType to, int semitones)
2010 {
2011         boost::shared_ptr<const MidiSource> s = midi_source ();
2012
2013         NoteDiffCommand* c = new_note_diff_command (_("transpose"));
2014
2015         for (Notes::iterator i = notes().begin(); i != notes().end(); ++i) {
2016
2017                 if ((*i)->time() >= to) {
2018
2019                         /* finished */
2020                         break;
2021
2022                 } else if ((*i)->time() >= from) {
2023
2024                         int new_note = (*i)->note() + semitones;
2025
2026                         if (new_note < 0) {
2027                                 new_note = 0;
2028                         } else if (new_note > 127) {
2029                                 new_note = 127;
2030                         }
2031
2032                         c->change (*i, NoteDiffCommand::NoteNumber, (uint8_t) new_note);
2033
2034                 }
2035         }
2036
2037         apply_command (s->session (), c);
2038 }
2039
2040 void
2041 MidiModel::control_list_marked_dirty ()
2042 {
2043         AutomatableSequence<Evoral::MusicalTime>::control_list_marked_dirty ();
2044         
2045         ContentsChanged (); /* EMIT SIGNAL */
2046 }