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