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