LTC encoder: clear user-bits
[ardour.git] / libs / ardour / midi_model.cc
index b6500563ba46604a376bd43548cf42baba6efb5a..4c6f6633d5e2a7ec90cd2dc3f3822f198f2d43ac 100644 (file)
 
 */
 
-#include <set>
-#include <iostream>
 #include <algorithm>
+#include <iostream>
+#include <set>
 #include <stdexcept>
 #include <stdint.h>
-#include "pbd/error.h"
-#include "pbd/enumwriter.h"
+
 #include "pbd/compose.h"
+#include "pbd/enumwriter.h"
+#include "pbd/error.h"
+
+#include "evoral/Control.hpp"
+
 #include "midi++/events.h"
 
+#include "ardour/automation_control.h"
+#include "ardour/midi_automation_list_binder.h"
 #include "ardour/midi_model.h"
 #include "ardour/midi_source.h"
 #include "ardour/midi_state_tracker.h"
-#include "ardour/smf_source.h"
-#include "ardour/types.h"
 #include "ardour/session.h"
-#include "ardour/midi_automation_list_binder.h"
+#include "ardour/types.h"
 
 #include "i18n.h"
 
@@ -503,8 +507,8 @@ MidiModel::NoteDiffCommand::unmarshal_note (XMLNode *xml_note)
        unsigned int note;
        XMLProperty* prop;
        unsigned int channel;
-       unsigned int time;
-       unsigned int length;
+       MidiModel::TimeType time;
+       MidiModel::TimeType length;
        unsigned int velocity;
        gint id;
 
@@ -782,6 +786,10 @@ MidiModel::SysExDiffCommand::operator() ()
        {
                MidiModel::WriteLock lock (_model->edit_lock ());
 
+               for (list<SysExPtr>::iterator i = _removed.begin(); i != _removed.end(); ++i) {
+                       _model->remove_sysex_unlocked (*i);
+               }
+
                for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
                        switch (i->property) {
                        case Time:
@@ -799,6 +807,10 @@ MidiModel::SysExDiffCommand::undo ()
        {
                MidiModel::WriteLock lock (_model->edit_lock ());
 
+               for (list<SysExPtr>::iterator i = _removed.begin(); i != _removed.end(); ++i) {
+                       _model->add_sysex_unlocked (*i);
+               }
+
                for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
                        switch (i->property) {
                        case Time:
@@ -812,6 +824,12 @@ MidiModel::SysExDiffCommand::undo ()
        _model->ContentsChanged(); /* EMIT SIGNAL */
 }
 
+void
+MidiModel::SysExDiffCommand::remove (SysExPtr sysex)
+{
+       _removed.push_back(sysex);
+}
+
 XMLNode&
 MidiModel::SysExDiffCommand::marshal_change (const Change& change)
 {
@@ -1415,7 +1433,6 @@ MidiModel::write_section_to (boost::shared_ptr<MidiSource> source, Evoral::Music
 {
        ReadLock lock(read_lock());
        MidiStateTracker mst;
-       Evoral::MusicalTime extra_note_on_time = end_time;
 
        const bool old_percussive = percussive();
        set_percussive(false);
@@ -1442,36 +1459,20 @@ MidiModel::write_section_to (boost::shared_ptr<MidiSource> source, Evoral::Music
                        if (mev->is_note_off()) {
 
                                if (!mst.active (mev->note(), mev->channel())) {
-
-                                       /* add a note-on at the start of the range we're writing
-                                          to the file. velocity is just an arbitary reasonable value.
+                                       /* the matching note-on was outside the
+                                          time range we were given, so just
+                                          ignore this note-off.
                                        */
-
-                                       Evoral::MIDIEvent<Evoral::MusicalTime> on (mev->event_type(), extra_note_on_time, 3, 0, true);
-                                       on.set_type (mev->type());
-                                       on.set_note (mev->note());
-                                       on.set_channel (mev->channel());
-                                       on.set_velocity (mev->velocity());
-
-                                       cerr << "Add note on for odd note off, note = " << (int) on.note() << endl;
-                                       source->append_event_unlocked_beats (on);
-                                       mst.add (on.note(), on.channel());
-                                       mst.dump (cerr);
-                                       extra_note_on_time += 1.0/128.0;
+                                       continue;
                                }
 
-                               cerr << "MIDI Note off (note = " << (int) mev->note() << endl;
                                source->append_event_unlocked_beats (*i);
                                mst.remove (mev->note(), mev->channel());
-                               mst.dump (cerr);
 
                        } else if (mev->is_note_on()) {
-                               cerr << "MIDI Note on (note = " << (int) mev->note() << endl;
                                mst.add (mev->note(), mev->channel());
                                source->append_event_unlocked_beats(*i);
-                               mst.dump (cerr);
                        } else {
-                               cerr << "MIDI other event type\n";
                                source->append_event_unlocked_beats(*i);
                        }
                }
@@ -1568,7 +1569,7 @@ MidiModel::edit_lock()
        boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
        assert (ms);
 
-       Glib::Mutex::Lock* source_lock = new Glib::Mutex::Lock (ms->mutex());
+       Glib::Threads::Mutex::Lock* source_lock = new Glib::Threads::Mutex::Lock (ms->mutex());
        ms->invalidate(); // Release cached iterator's read lock on model
        return WriteLock(new WriteLockImpl(source_lock, _lock, _control_lock));
 }
@@ -1820,7 +1821,7 @@ MidiModel::set_midi_source (boost::shared_ptr<MidiSource> s)
 void
 MidiModel::source_interpolation_changed (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
 {
-       Glib::Mutex::Lock lm (_control_lock);
+       Glib::Threads::Mutex::Lock lm (_control_lock);
        control(p)->list()->set_interpolation (s);
 }
 
@@ -1839,7 +1840,7 @@ MidiModel::control_list_interpolation_changed (Evoral::Parameter p, Evoral::Cont
 void
 MidiModel::source_automation_state_changed (Evoral::Parameter p, AutoState s)
 {
-       Glib::Mutex::Lock lm (_control_lock);
+       Glib::Threads::Mutex::Lock lm (_control_lock);
        boost::shared_ptr<AutomationList> al = boost::dynamic_pointer_cast<AutomationList> (control(p)->list ());
        al->set_automation_state (s);
 }
@@ -1880,7 +1881,7 @@ MidiModel::midi_source ()
        return _midi_source.lock ();
 }
 
-/** Moves notes, controllers and sys-ex to insert silence at the start of the model.
+/** Moves notes, patch changes, controllers and sys-ex to insert silence at the start of the model.
  *  Adds commands to the session's current undo stack to reflect the movements.
  */
 void
@@ -1901,6 +1902,18 @@ MidiModel::insert_silence_at_start (TimeType t)
                apply_command_as_subcommand (s->session(), c);
        }
 
+       /* Patch changes */
+
+       if (!patch_changes().empty ()) {
+               PatchChangeDiffCommand* c = new_patch_change_diff_command ("insert silence");
+
+               for (PatchChanges::const_iterator i = patch_changes().begin(); i != patch_changes().end(); ++i) {
+                       c->change_time (*i, (*i)->time() + t);
+               }
+
+               apply_command_as_subcommand (s->session(), c);
+       }
+
        /* Controllers */
 
        for (Controls::iterator i = controls().begin(); i != controls().end(); ++i) {
@@ -1963,3 +1976,11 @@ MidiModel::transpose (TimeType from, TimeType to, int semitones)
 
        apply_command (s->session (), c);
 }
+
+void
+MidiModel::control_list_marked_dirty ()
+{
+       AutomatableSequence<Evoral::MusicalTime>::control_list_marked_dirty ();
+       
+       ContentsChanged (); /* EMIT SIGNAL */
+}