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