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