Merge branch 'windows' of git.ardour.org:ardour/ardour into windows
[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                 /*NOTREACHED*/
199                 break;
200         case Length:
201                 fatal << "MidiModel::DiffCommand::change() with integer argument called for length" << endmsg;
202                 /*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                 /*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                 /*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                 /*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                 /*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                 /*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                 /*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
1022         _changes.push_back (c);
1023 }
1024
1025 void
1026 MidiModel::PatchChangeDiffCommand::change_program (PatchChangePtr patch, uint8_t program)
1027 {
1028         Change c;
1029         c.property = Program;
1030         c.patch = patch;
1031         c.old_program = patch->program ();
1032         c.new_program = program;
1033
1034         _changes.push_back (c);
1035 }
1036
1037 void
1038 MidiModel::PatchChangeDiffCommand::change_bank (PatchChangePtr patch, int bank)
1039 {
1040         Change c;
1041         c.property = Bank;
1042         c.patch = patch;
1043         c.old_bank = patch->bank ();
1044         c.new_bank = bank;
1045
1046         _changes.push_back (c);
1047 }
1048
1049 void
1050 MidiModel::PatchChangeDiffCommand::operator() ()
1051 {
1052         {
1053                 MidiModel::WriteLock lock (_model->edit_lock ());
1054
1055                 for (list<PatchChangePtr>::iterator i = _added.begin(); i != _added.end(); ++i) {
1056                         _model->add_patch_change_unlocked (*i);
1057                 }
1058
1059                 for (list<PatchChangePtr>::iterator i = _removed.begin(); i != _removed.end(); ++i) {
1060                         _model->remove_patch_change_unlocked (*i);
1061                 }
1062
1063                 /* find any patch change events that were missing when unmarshalling */
1064
1065                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
1066                         if (!i->patch) {
1067                                 i->patch = _model->find_patch_change (i->patch_id);
1068                                 assert (i->patch);
1069                         }
1070                 }
1071
1072                 set<PatchChangePtr> temporary_removals;
1073
1074                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
1075                         switch (i->property) {
1076                         case Time:
1077                                 if (temporary_removals.find (i->patch) == temporary_removals.end()) {
1078                                         _model->remove_patch_change_unlocked (i->patch);
1079                                         temporary_removals.insert (i->patch);
1080                                 }
1081                                 i->patch->set_time (i->new_time);
1082                                 break;
1083
1084                         case Channel:
1085                                 i->patch->set_channel (i->new_channel);
1086                                 break;
1087
1088                         case Program:
1089                                 i->patch->set_program (i->new_program);
1090                                 break;
1091
1092                         case Bank:
1093                                 i->patch->set_bank (i->new_bank);
1094                                 break;
1095                         }
1096                 }
1097
1098                 for (set<PatchChangePtr>::iterator i = temporary_removals.begin(); i != temporary_removals.end(); ++i) {
1099                         _model->add_patch_change_unlocked (*i);
1100                 }
1101         }
1102
1103         _model->ContentsChanged (); /* EMIT SIGNAL */
1104 }
1105
1106 void
1107 MidiModel::PatchChangeDiffCommand::undo ()
1108 {
1109         {
1110                 MidiModel::WriteLock lock (_model->edit_lock());
1111
1112                 for (list<PatchChangePtr>::iterator i = _added.begin(); i != _added.end(); ++i) {
1113                         _model->remove_patch_change_unlocked (*i);
1114                 }
1115
1116                 for (list<PatchChangePtr>::iterator i = _removed.begin(); i != _removed.end(); ++i) {
1117                         _model->add_patch_change_unlocked (*i);
1118                 }
1119
1120                 /* find any patch change events that were missing when unmarshalling */
1121
1122                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
1123                         if (!i->patch) {
1124                                 i->patch = _model->find_patch_change (i->patch_id);
1125                                 assert (i->patch);
1126                         }
1127                 }
1128
1129                 set<PatchChangePtr> temporary_removals;
1130
1131                 for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
1132                         switch (i->property) {
1133                         case Time:
1134                                 if (temporary_removals.find (i->patch) == temporary_removals.end()) {
1135                                         _model->remove_patch_change_unlocked (i->patch);
1136                                         temporary_removals.insert (i->patch);
1137                                 }
1138                                 i->patch->set_time (i->old_time);
1139                                 break;
1140
1141                         case Channel:
1142                                 i->patch->set_channel (i->old_channel);
1143                                 break;
1144
1145                         case Program:
1146                                 i->patch->set_program (i->old_program);
1147                                 break;
1148
1149                         case Bank:
1150                                 i->patch->set_bank (i->old_bank);
1151                                 break;
1152                         }
1153                 }
1154
1155                 for (set<PatchChangePtr>::iterator i = temporary_removals.begin(); i != temporary_removals.end(); ++i) {
1156                         _model->add_patch_change_unlocked (*i);
1157                 }
1158
1159         }
1160
1161         _model->ContentsChanged (); /* EMIT SIGNAL */
1162 }
1163
1164 XMLNode &
1165 MidiModel::PatchChangeDiffCommand::marshal_patch_change (constPatchChangePtr p)
1166 {
1167         XMLNode* n = new XMLNode ("patch-change");
1168
1169         {
1170                 ostringstream s (ios::ate);
1171                 s << int (p->id ());
1172                 n->add_property ("id", s.str());
1173         }
1174
1175         {
1176                 ostringstream s (ios::ate);
1177                 s << p->time ();
1178                 n->add_property ("time", s.str ());
1179         }
1180
1181         {
1182                 ostringstream s (ios::ate);
1183                 s << int (p->channel ());
1184                 n->add_property ("channel", s.str ());
1185         }
1186
1187         {
1188                 ostringstream s (ios::ate);
1189                 s << int (p->program ());
1190                 n->add_property ("program", s.str ());
1191         }
1192
1193         {
1194                 ostringstream s (ios::ate);
1195                 s << int (p->bank ());
1196                 n->add_property ("bank", s.str ());
1197         }
1198
1199         return *n;
1200 }
1201
1202 XMLNode&
1203 MidiModel::PatchChangeDiffCommand::marshal_change (const Change& c)
1204 {
1205         XMLNode* n = new XMLNode (X_("Change"));
1206
1207         n->add_property (X_("property"), enum_2_string (c.property));
1208
1209         {
1210                 ostringstream s (ios::ate);
1211                 if (c.property == Time) {
1212                         s << c.old_time;
1213                 } else if (c.property == Channel) {
1214                         s << c.old_channel;
1215                 } else if (c.property == Program) {
1216                         s << int (c.old_program);
1217                 } else if (c.property == Bank) {
1218                         s << c.old_bank;
1219                 }
1220
1221                 n->add_property (X_("old"), s.str ());
1222         }
1223
1224         {
1225                 ostringstream s (ios::ate);
1226
1227                 if (c.property == Time) {
1228                         s << c.new_time;
1229                 } else if (c.property == Channel) {
1230                         s << c.new_channel;
1231                 } else if (c.property == Program) {
1232                         s << int (c.new_program);
1233                 } else if (c.property == Bank) {
1234                         s << c.new_bank;
1235                 }
1236
1237                 n->add_property (X_("new"), s.str ());
1238         }
1239
1240         {
1241                 ostringstream s;
1242                 s << c.patch->id ();
1243                 n->add_property ("id", s.str ());
1244         }
1245
1246         return *n;
1247 }
1248
1249 MidiModel::PatchChangePtr
1250 MidiModel::PatchChangeDiffCommand::unmarshal_patch_change (XMLNode* n)
1251 {
1252         XMLProperty* prop;
1253         Evoral::event_id_t id;
1254         Evoral::MusicalTime time = 0;
1255         int channel = 0;
1256         int program = 0;
1257         int bank = 0;
1258         
1259         if ((prop = n->property ("id")) != 0) {
1260                 istringstream s (prop->value());
1261                 s >> id;
1262         }
1263
1264         if ((prop = n->property ("time")) != 0) {
1265                 istringstream s (prop->value ());
1266                 s >> time;
1267         }
1268
1269         if ((prop = n->property ("channel")) != 0) {
1270                 istringstream s (prop->value ());
1271                 s >> channel;
1272         }
1273
1274         if ((prop = n->property ("program")) != 0) {
1275                 istringstream s (prop->value ());
1276                 s >> program;
1277         }
1278
1279         if ((prop = n->property ("bank")) != 0) {
1280                 istringstream s (prop->value ());
1281                 s >> bank;
1282         }
1283
1284         PatchChangePtr p (new Evoral::PatchChange<TimeType> (time, channel, program, bank));
1285         p->set_id (id);
1286         return p;
1287 }
1288
1289 MidiModel::PatchChangeDiffCommand::Change
1290 MidiModel::PatchChangeDiffCommand::unmarshal_change (XMLNode* n)
1291 {
1292         XMLProperty* prop;
1293         Change c;
1294         int an_int;
1295
1296         prop = n->property ("property");
1297         assert (prop);
1298         c.property = (Property) string_2_enum (prop->value(), c.property);
1299
1300         prop = n->property ("id");
1301         assert (prop);
1302         Evoral::event_id_t const id = atoi (prop->value().c_str());
1303
1304         /* we need to load via an int intermediate for all properties that are 
1305            actually uint8_t (char/byte).
1306         */
1307
1308         prop = n->property ("old");
1309         assert (prop);
1310         {
1311                 istringstream s (prop->value ());
1312                 if (c.property == Time) {
1313                         s >> c.old_time;
1314                 } else if (c.property == Channel) {
1315                         s >> an_int;
1316                         c.old_channel = an_int;
1317                 } else if (c.property == Program) {
1318                         s >> an_int;
1319                         c.old_program = an_int;
1320                 } else if (c.property == Bank) {
1321                         s >> an_int;
1322                         c.old_bank = an_int;
1323                 }
1324         }
1325
1326         prop = n->property ("new");
1327         assert (prop);
1328         {
1329                 istringstream s (prop->value ());
1330
1331                 if (c.property == Time) {
1332                         s >> c.new_time;
1333                 } else if (c.property == Channel) {
1334                         s >> an_int;
1335                         c.new_channel = an_int;
1336                 } else if (c.property == Program) {
1337                         s >> an_int;
1338                         c.new_program = an_int;
1339                 } else if (c.property == Bank) {
1340                         s >> an_int;
1341                         c.new_bank = an_int;
1342                 }
1343         }
1344
1345         c.patch = _model->find_patch_change (id);
1346         c.patch_id = id;
1347
1348         return c;
1349 }
1350
1351 int
1352 MidiModel::PatchChangeDiffCommand::set_state (const XMLNode& diff_command, int /*version*/)
1353 {
1354         if (diff_command.name() != PATCH_CHANGE_DIFF_COMMAND_ELEMENT) {
1355                 return 1;
1356         }
1357
1358         _added.clear ();
1359         XMLNode* added = diff_command.child (ADDED_PATCH_CHANGES_ELEMENT);
1360         if (added) {
1361                 XMLNodeList p = added->children ();
1362                 transform (p.begin(), p.end(), back_inserter (_added), boost::bind (&PatchChangeDiffCommand::unmarshal_patch_change, this, _1));
1363         }
1364
1365         _removed.clear ();
1366         XMLNode* removed = diff_command.child (REMOVED_PATCH_CHANGES_ELEMENT);
1367         if (removed) {
1368                 XMLNodeList p = removed->children ();
1369                 transform (p.begin(), p.end(), back_inserter (_removed), boost::bind (&PatchChangeDiffCommand::unmarshal_patch_change, this, _1));
1370         }
1371
1372         _changes.clear ();
1373         XMLNode* changed = diff_command.child (DIFF_PATCH_CHANGES_ELEMENT);
1374         if (changed) {
1375                 XMLNodeList p = changed->children ();
1376                 transform (p.begin(), p.end(), back_inserter (_changes), boost::bind (&PatchChangeDiffCommand::unmarshal_change, this, _1));
1377         }
1378
1379         return 0;
1380 }
1381
1382 XMLNode &
1383 MidiModel::PatchChangeDiffCommand::get_state ()
1384 {
1385         XMLNode* diff_command = new XMLNode (PATCH_CHANGE_DIFF_COMMAND_ELEMENT);
1386         diff_command->add_property("midi-source", _model->midi_source()->id().to_s());
1387
1388         XMLNode* added = diff_command->add_child (ADDED_PATCH_CHANGES_ELEMENT);
1389         for_each (_added.begin(), _added.end(),
1390                   boost::bind (
1391                           boost::bind (&XMLNode::add_child_nocopy, added, _1),
1392                           boost::bind (&PatchChangeDiffCommand::marshal_patch_change, this, _1)
1393                           )
1394                 );
1395
1396         XMLNode* removed = diff_command->add_child (REMOVED_PATCH_CHANGES_ELEMENT);
1397         for_each (_removed.begin(), _removed.end(),
1398                   boost::bind (
1399                           boost::bind (&XMLNode::add_child_nocopy, removed, _1),
1400                           boost::bind (&PatchChangeDiffCommand::marshal_patch_change, this, _1)
1401                           )
1402                 );
1403
1404         XMLNode* changes = diff_command->add_child (DIFF_PATCH_CHANGES_ELEMENT);
1405         for_each (_changes.begin(), _changes.end(),
1406                   boost::bind (
1407                           boost::bind (&XMLNode::add_child_nocopy, changes, _1),
1408                           boost::bind (&PatchChangeDiffCommand::marshal_change, this, _1)
1409                           )
1410                 );
1411
1412         return *diff_command;
1413 }
1414
1415 /** Write all of the model to a MidiSource (i.e. save the model).
1416  * This is different from manually using read to write to a source in that
1417  * note off events are written regardless of the track mode.  This is so the
1418  * user can switch a recorded track (with note durations from some instrument)
1419  * to percussive, save, reload, then switch it back to sustained without
1420  * destroying the original note durations.
1421  *
1422  * Similarly, control events are written without interpolation (as with the
1423  * `Discrete' mode).
1424  */
1425 bool
1426 MidiModel::write_to (boost::shared_ptr<MidiSource> source)
1427 {
1428         ReadLock lock(read_lock());
1429
1430         const bool old_percussive = percussive();
1431         set_percussive(false);
1432
1433         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1434         assert (ms);
1435
1436         source->drop_model();
1437         source->mark_streaming_midi_write_started (note_mode());
1438
1439         for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
1440                 source->append_event_unlocked_beats(*i);
1441         }
1442
1443         set_percussive(old_percussive);
1444         source->mark_streaming_write_completed();
1445
1446         set_edited(false);
1447
1448         return true;
1449 }
1450
1451 /** very similar to ::write_to() but writes to the model's own
1452     existing midi_source, without making it call MidiSource::drop_model().
1453     the caller is a MidiSource that needs to catch up with the state
1454     of the model.
1455 */
1456 bool
1457 MidiModel::sync_to_source ()
1458 {
1459         ReadLock lock(read_lock());
1460
1461         const bool old_percussive = percussive();
1462         set_percussive(false);
1463
1464         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1465         assert (ms);
1466
1467         ms->mark_streaming_midi_write_started (note_mode());
1468
1469         for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
1470                 ms->append_event_unlocked_beats(*i);
1471         }
1472
1473         set_percussive (old_percussive);
1474         ms->mark_streaming_write_completed ();
1475
1476         set_edited (false);
1477
1478         return true;
1479 }
1480
1481 /** Write part or all of the model to a MidiSource (i.e. save the model).
1482  * This is different from manually using read to write to a source in that
1483  * note off events are written regardless of the track mode.  This is so the
1484  * user can switch a recorded track (with note durations from some instrument)
1485  * to percussive, save, reload, then switch it back to sustained without
1486  * destroying the original note durations.
1487  */
1488 bool
1489 MidiModel::write_section_to (boost::shared_ptr<MidiSource> source, Evoral::MusicalTime begin_time, Evoral::MusicalTime end_time)
1490 {
1491         ReadLock lock(read_lock());
1492         MidiStateTracker mst;
1493
1494         const bool old_percussive = percussive();
1495         set_percussive(false);
1496
1497         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1498         assert (ms);
1499
1500         source->drop_model();
1501         source->mark_streaming_midi_write_started (note_mode());
1502
1503         for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
1504                 const Evoral::Event<Evoral::MusicalTime>& ev (*i);
1505
1506                 if (ev.time() >= begin_time && ev.time() < end_time) {
1507
1508                         const Evoral::MIDIEvent<Evoral::MusicalTime>* mev =
1509                                 static_cast<const Evoral::MIDIEvent<Evoral::MusicalTime>* > (&ev);
1510
1511                         if (!mev) {
1512                                 continue;
1513                         }
1514
1515
1516                         if (mev->is_note_off()) {
1517
1518                                 if (!mst.active (mev->note(), mev->channel())) {
1519                                         /* the matching note-on was outside the
1520                                            time range we were given, so just
1521                                            ignore this note-off.
1522                                         */
1523                                         continue;
1524                                 }
1525
1526                                 source->append_event_unlocked_beats (*i);
1527                                 mst.remove (mev->note(), mev->channel());
1528
1529                         } else if (mev->is_note_on()) {
1530                                 mst.add (mev->note(), mev->channel());
1531                                 source->append_event_unlocked_beats(*i);
1532                         } else {
1533                                 source->append_event_unlocked_beats(*i);
1534                         }
1535                 }
1536         }
1537
1538         mst.resolve_notes (*source, end_time);
1539
1540         set_percussive(old_percussive);
1541         source->mark_streaming_write_completed();
1542
1543         set_edited(false);
1544
1545         return true;
1546 }
1547
1548 XMLNode&
1549 MidiModel::get_state()
1550 {
1551         XMLNode *node = new XMLNode("MidiModel");
1552         return *node;
1553 }
1554
1555 Evoral::Sequence<MidiModel::TimeType>::NotePtr
1556 MidiModel::find_note (NotePtr other)
1557 {
1558         Notes::iterator l = notes().lower_bound(other);
1559
1560         if (l != notes().end()) {
1561                 for (; (*l)->time() == other->time(); ++l) {
1562                         /* NB: compare note contents, not note pointers.
1563                            If "other" was a ptr to a note already in
1564                            the model, we wouldn't be looking for it,
1565                            would we now?
1566                         */
1567                         if (**l == *other) {
1568                                 return *l;
1569                         }
1570                 }
1571         }
1572
1573         return NotePtr();
1574 }
1575
1576 Evoral::Sequence<MidiModel::TimeType>::NotePtr
1577 MidiModel::find_note (gint note_id)
1578 {
1579         /* used only for looking up notes when reloading history from disk,
1580            so we don't care about performance *too* much.
1581         */
1582
1583         for (Notes::iterator l = notes().begin(); l != notes().end(); ++l) {
1584                 if ((*l)->id() == note_id) {
1585                         return *l;
1586                 }
1587         }
1588
1589         return NotePtr();
1590 }
1591
1592 MidiModel::PatchChangePtr
1593 MidiModel::find_patch_change (Evoral::event_id_t id)
1594 {
1595         for (PatchChanges::iterator i = patch_changes().begin(); i != patch_changes().end(); ++i) {
1596                 if ((*i)->id() == id) {
1597                         return *i;
1598                 }
1599         }
1600
1601         return PatchChangePtr ();
1602 }
1603
1604 boost::shared_ptr<Evoral::Event<MidiModel::TimeType> >
1605 MidiModel::find_sysex (gint sysex_id)
1606 {
1607         /* used only for looking up notes when reloading history from disk,
1608            so we don't care about performance *too* much.
1609         */
1610
1611         for (SysExes::iterator l = sysexes().begin(); l != sysexes().end(); ++l) {
1612                 if ((*l)->id() == sysex_id) {
1613                         return *l;
1614                 }
1615         }
1616
1617         return boost::shared_ptr<Evoral::Event<TimeType> > ();
1618 }
1619
1620 /** Lock and invalidate the source.
1621  * This should be used by commands and editing things
1622  */
1623 MidiModel::WriteLock
1624 MidiModel::edit_lock()
1625 {
1626         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1627         assert (ms);
1628
1629         Glib::Threads::Mutex::Lock* source_lock = new Glib::Threads::Mutex::Lock (ms->mutex());
1630         ms->invalidate(); // Release cached iterator's read lock on model
1631         return WriteLock(new WriteLockImpl(source_lock, _lock, _control_lock));
1632 }
1633
1634 /** Lock just the model, the source lock must already be held.
1635  * This should only be called from libardour/evoral places
1636  */
1637 MidiModel::WriteLock
1638 MidiModel::write_lock()
1639 {
1640         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1641         assert (ms);
1642
1643         assert (!ms->mutex().trylock ());
1644         return WriteLock(new WriteLockImpl(0, _lock, _control_lock));
1645 }
1646
1647 int
1648 MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg)
1649 {
1650         using namespace Evoral;
1651
1652         if (_writing || insert_merge_policy() == InsertMergeRelax) {
1653                 return 0;
1654         }
1655
1656         NoteDiffCommand* cmd = static_cast<NoteDiffCommand*>(arg);
1657
1658         TimeType sa = note->time();
1659         TimeType ea  = note->end_time();
1660
1661         const Pitches& p (pitches (note->channel()));
1662         NotePtr search_note(new Note<TimeType>(0, 0, 0, note->note()));
1663         set<NotePtr> to_be_deleted;
1664         bool set_note_length = false;
1665         bool set_note_time = false;
1666         TimeType note_time = note->time();
1667         TimeType note_length = note->length();
1668
1669         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 checking overlaps for note %2 @ %3\n", this, (int)note->note(), note->time()));
1670
1671         for (Pitches::const_iterator i = p.lower_bound (search_note);
1672              i != p.end() && (*i)->note() == note->note(); ++i) {
1673
1674                 TimeType sb = (*i)->time();
1675                 TimeType eb = (*i)->end_time();
1676                 OverlapType overlap = OverlapNone;
1677
1678                 if ((sb > sa) && (eb <= ea)) {
1679                         overlap = OverlapInternal;
1680                 } else if ((eb >= sa) && (eb <= ea)) {
1681                         overlap = OverlapStart;
1682                 } else if ((sb > sa) && (sb <= ea)) {
1683                         overlap = OverlapEnd;
1684                 } else if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
1685                         overlap = OverlapExternal;
1686                 } else {
1687                         /* no overlap */
1688                         continue;
1689                 }
1690
1691                 DEBUG_TRACE (DEBUG::Sequence, string_compose (
1692                                      "\toverlap is %1 for (%2,%3) vs (%4,%5)\n",
1693                                      enum_2_string(overlap), sa, ea, sb, eb));
1694
1695                 if (insert_merge_policy() == InsertMergeReject) {
1696                         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 just reject\n", this));
1697                         return -1;
1698                 }
1699
1700                 switch (overlap) {
1701                 case OverlapStart:
1702                         cerr << "OverlapStart\n";
1703                         /* existing note covers start of new note */
1704                         switch (insert_merge_policy()) {
1705                         case InsertMergeReplace:
1706                                 to_be_deleted.insert (*i);
1707                                 break;
1708                         case InsertMergeTruncateExisting:
1709                                 if (cmd) {
1710                                         cmd->change (*i, NoteDiffCommand::Length, (note->time() - (*i)->time()));
1711                                 }
1712                                 (*i)->set_length (note->time() - (*i)->time());
1713                                 break;
1714                         case InsertMergeTruncateAddition:
1715                                 set_note_time = true;
1716                                 set_note_length = true;
1717                                 note_time = (*i)->time() + (*i)->length();
1718                                 note_length = min (note_length, (*i)->length() - ((*i)->end_time() - note->time()));
1719                                 break;
1720                         case InsertMergeExtend:
1721                                 if (cmd) {
1722                                         cmd->change ((*i), NoteDiffCommand::Length, note->end_time() - (*i)->time());
1723                                 }
1724                                 (*i)->set_length (note->end_time() - (*i)->time());
1725                                 return -1; /* do not add the new note */
1726                                 break;
1727                         default:
1728                                 /*NOTREACHED*/
1729                                 /* stupid gcc */
1730                                 break;
1731                         }
1732                         break;
1733
1734                 case OverlapEnd:
1735                         cerr << "OverlapEnd\n";
1736                         /* existing note covers end of new note */
1737                         switch (insert_merge_policy()) {
1738                         case InsertMergeReplace:
1739                                 to_be_deleted.insert (*i);
1740                                 break;
1741
1742                         case InsertMergeTruncateExisting:
1743                                 /* resetting the start time of the existing note
1744                                    is a problem because of time ordering.
1745                                 */
1746                                 break;
1747
1748                         case InsertMergeTruncateAddition:
1749                                 set_note_length = true;
1750                                 note_length = min (note_length, ((*i)->time() - note->time()));
1751                                 break;
1752
1753                         case InsertMergeExtend:
1754                                 /* we can't reset the time of the existing note because
1755                                    that will corrupt time ordering. So remove the
1756                                    existing note and change the position/length
1757                                    of the new note (which has not been added yet)
1758                                 */
1759                                 to_be_deleted.insert (*i);
1760                                 set_note_length = true;
1761                                 note_length = min (note_length, (*i)->end_time() - note->time());
1762                                 break;
1763                         default:
1764                                 /*NOTREACHED*/
1765                                 /* stupid gcc */
1766                                 break;
1767                         }
1768                         break;
1769
1770                 case OverlapExternal:
1771                         cerr << "OverlapExt\n";
1772                         /* existing note overlaps all the new note */
1773                         switch (insert_merge_policy()) {
1774                         case InsertMergeReplace:
1775                                 to_be_deleted.insert (*i);
1776                                 break;
1777                         case InsertMergeTruncateExisting:
1778                         case InsertMergeTruncateAddition:
1779                         case InsertMergeExtend:
1780                                 /* cannot add in this case */
1781                                 return -1;
1782                         default:
1783                                 /*NOTREACHED*/
1784                                 /* stupid gcc */
1785                                 break;
1786                         }
1787                         break;
1788
1789                 case OverlapInternal:
1790                         cerr << "OverlapInt\n";
1791                         /* new note fully overlaps an existing note */
1792                         switch (insert_merge_policy()) {
1793                         case InsertMergeReplace:
1794                         case InsertMergeTruncateExisting:
1795                         case InsertMergeTruncateAddition:
1796                         case InsertMergeExtend:
1797                                 /* delete the existing note, the new one will cover it */
1798                                 to_be_deleted.insert (*i);
1799                                 break;
1800                         default:
1801                                 /*NOTREACHED*/
1802                                 /* stupid gcc */
1803                                 break;
1804                         }
1805                         break;
1806
1807                 default:
1808                         /*NOTREACHED*/
1809                         /* stupid gcc */
1810                         break;
1811                 }
1812         }
1813
1814         for (set<NotePtr>::iterator i = to_be_deleted.begin(); i != to_be_deleted.end(); ++i) {
1815                 remove_note_unlocked (*i);
1816
1817                 if (cmd) {
1818                         cmd->side_effect_remove (*i);
1819                 }
1820         }
1821
1822         if (set_note_time) {
1823                 if (cmd) {
1824                         cmd->change (note, NoteDiffCommand::StartTime, note_time);
1825                 }
1826                 note->set_time (note_time);
1827         }
1828
1829         if (set_note_length) {
1830                 if (cmd) {
1831                         cmd->change (note, NoteDiffCommand::Length, note_length);
1832                 }
1833                 note->set_length (note_length);
1834         }
1835
1836         return 0;
1837 }
1838
1839 InsertMergePolicy
1840 MidiModel::insert_merge_policy () const
1841 {
1842         /* XXX ultimately this should be a per-track or even per-model policy */
1843         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1844         assert (ms);
1845
1846         return ms->session().config.get_insert_merge_policy ();
1847 }
1848
1849 void
1850 MidiModel::set_midi_source (boost::shared_ptr<MidiSource> s)
1851 {
1852         boost::shared_ptr<MidiSource> old = _midi_source.lock ();
1853
1854         if (old) {
1855                 old->invalidate ();
1856         }
1857
1858         _midi_source_connections.drop_connections ();
1859
1860         _midi_source = s;
1861
1862         s->InterpolationChanged.connect_same_thread (
1863                 _midi_source_connections, boost::bind (&MidiModel::source_interpolation_changed, this, _1, _2)
1864                 );
1865
1866         s->AutomationStateChanged.connect_same_thread (
1867                 _midi_source_connections, boost::bind (&MidiModel::source_automation_state_changed, this, _1, _2)
1868                 );
1869 }
1870
1871 /** The source has signalled that the interpolation style for a parameter has changed.  In order to
1872  *  keep MidiSource and ControlList interpolation state the same, we pass this change onto the
1873  *  appropriate ControlList.
1874  *
1875  *  The idea is that MidiSource and the MidiModel's ControlList states are kept in sync, and one
1876  *  or the other is listened to by the GUI.
1877  */
1878 void
1879 MidiModel::source_interpolation_changed (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
1880 {
1881         Glib::Threads::Mutex::Lock lm (_control_lock);
1882         control(p)->list()->set_interpolation (s);
1883 }
1884
1885 /** A ControlList has signalled that its interpolation style has changed.  Again, in order to keep
1886  *  MidiSource and ControlList interpolation state in sync, we pass this change onto our MidiSource.
1887  */
1888 void
1889 MidiModel::control_list_interpolation_changed (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
1890 {
1891         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1892         assert (ms);
1893
1894         ms->set_interpolation_of (p, s);
1895 }
1896
1897 void
1898 MidiModel::source_automation_state_changed (Evoral::Parameter p, AutoState s)
1899 {
1900         Glib::Threads::Mutex::Lock lm (_control_lock);
1901         boost::shared_ptr<AutomationList> al = boost::dynamic_pointer_cast<AutomationList> (control(p)->list ());
1902         al->set_automation_state (s);
1903 }
1904
1905 void
1906 MidiModel::automation_list_automation_state_changed (Evoral::Parameter p, AutoState s)
1907 {
1908         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1909         assert (ms);
1910         ms->set_automation_state_of (p, s);
1911 }
1912
1913 boost::shared_ptr<Evoral::Control>
1914 MidiModel::control_factory (Evoral::Parameter const & p)
1915 {
1916         boost::shared_ptr<Evoral::Control> c = Automatable::control_factory (p);
1917
1918         /* Set up newly created control's lists to the appropriate interpolation and
1919            automation state from our source.
1920         */
1921
1922         boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
1923         assert (ms);
1924
1925         c->list()->set_interpolation (ms->interpolation_of (p));
1926
1927         boost::shared_ptr<AutomationList> al = boost::dynamic_pointer_cast<AutomationList> (c->list ());
1928         assert (al);
1929
1930         al->set_automation_state (ms->automation_state_of (p));
1931
1932         return c;
1933 }
1934
1935 boost::shared_ptr<const MidiSource>
1936 MidiModel::midi_source ()
1937 {
1938         return _midi_source.lock ();
1939 }
1940
1941 /** Moves notes, patch changes, controllers and sys-ex to insert silence at the start of the model.
1942  *  Adds commands to the session's current undo stack to reflect the movements.
1943  */
1944 void
1945 MidiModel::insert_silence_at_start (TimeType t)
1946 {
1947         boost::shared_ptr<MidiSource> s = _midi_source.lock ();
1948         assert (s);
1949
1950         /* Notes */
1951
1952         if (!notes().empty ()) {
1953                 NoteDiffCommand* c = new_note_diff_command ("insert silence");
1954
1955                 for (Notes::const_iterator i = notes().begin(); i != notes().end(); ++i) {
1956                         c->change (*i, NoteDiffCommand::StartTime, (*i)->time() + t);
1957                 }
1958
1959                 apply_command_as_subcommand (s->session(), c);
1960         }
1961
1962         /* Patch changes */
1963
1964         if (!patch_changes().empty ()) {
1965                 PatchChangeDiffCommand* c = new_patch_change_diff_command ("insert silence");
1966
1967                 for (PatchChanges::const_iterator i = patch_changes().begin(); i != patch_changes().end(); ++i) {
1968                         c->change_time (*i, (*i)->time() + t);
1969                 }
1970
1971                 apply_command_as_subcommand (s->session(), c);
1972         }
1973
1974         /* Controllers */
1975
1976         for (Controls::iterator i = controls().begin(); i != controls().end(); ++i) {
1977                 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (i->second);
1978                 XMLNode& before = ac->alist()->get_state ();
1979                 i->second->list()->shift (0, t);
1980                 XMLNode& after = ac->alist()->get_state ();
1981                 s->session().add_command (new MementoCommand<AutomationList> (new MidiAutomationListBinder (s, i->first), &before, &after));
1982         }
1983
1984         /* Sys-ex */
1985
1986         if (!sysexes().empty()) {
1987                 SysExDiffCommand* c = new_sysex_diff_command ("insert silence");
1988
1989                 for (SysExes::iterator i = sysexes().begin(); i != sysexes().end(); ++i) {
1990                         c->change (*i, (*i)->time() + t);
1991                 }
1992
1993                 apply_command_as_subcommand (s->session(), c);
1994         }
1995 }
1996
1997 /** Transpose notes in a time range by a given number of semitones.  Notes
1998  *  will be clamped at 0 and 127 if the transposition would make them exceed
1999  *  that range.
2000  *
2001  *  @param from Start time.
2002  *  @param end End time.
2003  *  @param semitones Number of semitones to transpose by (+ve is higher, -ve is lower).
2004  */
2005 void
2006 MidiModel::transpose (TimeType from, TimeType to, int semitones)
2007 {
2008         boost::shared_ptr<const MidiSource> s = midi_source ();
2009
2010         NoteDiffCommand* c = new_note_diff_command (_("transpose"));
2011
2012         for (Notes::iterator i = notes().begin(); i != notes().end(); ++i) {
2013
2014                 if ((*i)->time() >= to) {
2015
2016                         /* finished */
2017                         break;
2018
2019                 } else if ((*i)->time() >= from) {
2020
2021                         int new_note = (*i)->note() + semitones;
2022
2023                         if (new_note < 0) {
2024                                 new_note = 0;
2025                         } else if (new_note > 127) {
2026                                 new_note = 127;
2027                         }
2028
2029                         c->change (*i, NoteDiffCommand::NoteNumber, (uint8_t) new_note);
2030
2031                 }
2032         }
2033
2034         apply_command (s->session (), c);
2035 }
2036
2037 void
2038 MidiModel::control_list_marked_dirty ()
2039 {
2040         AutomatableSequence<Evoral::MusicalTime>::control_list_marked_dirty ();
2041         
2042         ContentsChanged (); /* EMIT SIGNAL */
2043 }