Handle overlaps better when executing DiffCommands.
authorCarl Hetherington <carl@carlh.net>
Thu, 9 Dec 2010 21:37:14 +0000 (21:37 +0000)
committerCarl Hetherington <carl@carlh.net>
Thu, 9 Dec 2010 21:37:14 +0000 (21:37 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@8233 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/midi_model.h
libs/ardour/midi_model.cc

index 532d8c0e9493beed02ca76d044f204b33b077764..83fe00567a349c91234fbe6147c9c5509abe4dfa 100644 (file)
@@ -141,9 +141,9 @@ public:
        };
 
        /* Currently this class only supports changes of sys-ex time, but could be expanded */
-       class SysexDiffCommand : public DiffCommand {
+       class SysExDiffCommand : public DiffCommand {
        public:
-               SysexDiffCommand (boost::shared_ptr<MidiModel> m, const XMLNode& node);
+               SysExDiffCommand (boost::shared_ptr<MidiModel> m, const XMLNode& node);
                
                enum Property {
                        Time,
@@ -160,7 +160,7 @@ public:
        private:
                struct Change {
                        boost::shared_ptr<Evoral::Event<TimeType> > sysex;
-                       SysexDiffCommand::Property property;
+                       SysExDiffCommand::Property property;
                        TimeType old_time;
                        TimeType new_time;
                };
@@ -172,7 +172,8 @@ public:
                Change unmarshal_change (XMLNode *);
        };
 
-       MidiModel::NoteDiffCommand* new_note_diff_command (const std::string name="midi edit");
+       MidiModel::NoteDiffCommand* new_note_diff_command (const std::string name = "midi edit");
+       MidiModel::SysExDiffCommand* new_sysex_diff_command (const std::string name = "midi edit");
        void apply_command (Session& session, Command* cmd);
        void apply_command_as_subcommand (Session& session, Command* cmd);
 
index b93e74ef9365a5fec784138fd1f68069758d4754..be8e97b055b757856fa8fcb9858ff069bbdbc1ac 100644 (file)
@@ -147,6 +147,8 @@ void
 MidiModel::NoteDiffCommand::change (const NotePtr note, Property prop,
                                    uint8_t new_value)
 {
+       assert (note);
+       
         NoteChange change;
         
         switch (prop) {
@@ -191,6 +193,8 @@ void
 MidiModel::NoteDiffCommand::change (const NotePtr note, Property prop,
                                    TimeType new_time)
 {
+       assert (note);
+       
         NoteChange change;
 
         switch (prop) {
@@ -307,8 +311,30 @@ MidiModel::NoteDiffCommand::operator() ()
 
                 for (set<NotePtr>::iterator i = temporary_removals.begin(); i != temporary_removals.end(); ++i) {
                         NoteDiffCommand side_effects (model(), "side effects");
-                        _model->add_note_unlocked (*i, &side_effects);
-                        *this += side_effects;
+                       if (_model->add_note_unlocked (*i, &side_effects)) {
+                               /* The note was re-added ok */
+                               *this += side_effects;
+                       } else {
+                               /* The note that we removed earlier could not be re-added.  This change record
+                                  must say that the note was removed.  It is an un-note.
+                               */
+
+                               /* We didn't change it... */
+                               for (ChangeList::iterator j = _changes.begin(); j != _changes.end(); ) {
+
+                                       ChangeList::iterator k = j;
+                                       ++k;
+                                       
+                                       if (*i == j->note) {
+                                               _changes.erase (j);
+                                       }
+
+                                       j = k;
+                               }
+
+                               /* ...in fact, we removed it */
+                               _removed_notes.push_back (*i);
+                       }
                 }
 
                 if (!side_effect_removals.empty()) {
@@ -1124,7 +1150,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg)
         TimeType note_length = note->length();
 
        DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 checking overlaps for note %2 @ %3\n", this, (int)note->note(), note->time()));
-
+       
         for (Pitches::const_iterator i = p.lower_bound (search_note); 
              i != p.end() && (*i)->note() == note->note(); ++i) {
 
@@ -1132,7 +1158,6 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg)
                 TimeType eb = (*i)->end_time();
                 OverlapType overlap = OverlapNone;
 
-
                 if ((sb > sa) && (eb <= ea)) {
                         overlap = OverlapInternal;
                 } else if ((eb >= sa) && (eb <= ea)) {
@@ -1146,7 +1171,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg)
                         continue;
                 }
 
-                DEBUG_TRACE (DEBUG::Sequence, string_compose ("\toverlap is %1 for (%2,%3) vs (%4,%5)\n", enum_2_string(overlap), 
+               DEBUG_TRACE (DEBUG::Sequence, string_compose ("\toverlap is %1 for (%2,%3) vs (%4,%5)\n", enum_2_string(overlap), 
                                                               sa, ea, sb, eb));
 
                 if (insert_merge_policy() == InsertMergeReject) {