summaryrefslogtreecommitdiff
path: root/libs/ardour/midi_model.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour/midi_model.cc')
-rw-r--r--libs/ardour/midi_model.cc62
1 files changed, 57 insertions, 5 deletions
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index 6e2c477a99..b5d5d24713 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -41,8 +41,9 @@ using namespace PBD;
MidiModel::MidiModel(MidiSource* s)
: AutomatableSequence<TimeType>(s->session())
- , _midi_source(s)
+ , _midi_source (0)
{
+ set_midi_source (s);
}
/** Start a new Diff command.
@@ -761,6 +762,9 @@ MidiModel::DiffCommand::get_state ()
* user can switch a recorded track (with note durations from some instrument)
* to percussive, save, reload, then switch it back to sustained without
* destroying the original note durations.
+ *
+ * Similarly, control events are written without interpolation (as with the
+ * `Discrete' mode).
*/
bool
MidiModel::write_to (boost::shared_ptr<MidiSource> source)
@@ -773,7 +777,7 @@ MidiModel::write_to (boost::shared_ptr<MidiSource> source)
source->drop_model();
source->mark_streaming_midi_write_started(note_mode(), _midi_source->timeline_position());
- for (Evoral::Sequence<TimeType>::const_iterator i = begin(); i != end(); ++i) {
+ for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
source->append_event_unlocked_beats(*i);
}
@@ -800,7 +804,7 @@ MidiModel::sync_to_source ()
_midi_source->mark_streaming_midi_write_started(note_mode(), _midi_source->timeline_position());
- for (Evoral::Sequence<TimeType>::const_iterator i = begin(); i != end(); ++i) {
+ for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
_midi_source->append_event_unlocked_beats(*i);
}
@@ -832,7 +836,7 @@ MidiModel::write_section_to (boost::shared_ptr<MidiSource> source, Evoral::Music
source->drop_model();
source->mark_streaming_midi_write_started(note_mode(), _midi_source->timeline_position());
- for (Evoral::Sequence<TimeType>::const_iterator i = begin(); i != end(); ++i) {
+ for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
const Evoral::Event<Evoral::MusicalTime>& ev (*i);
if (ev.time() >= begin_time && ev.time() < end_time) {
@@ -1138,6 +1142,54 @@ MidiModel::insert_merge_policy () const
void
MidiModel::set_midi_source (MidiSource* s)
{
- _midi_source->invalidate ();
+ if (_midi_source) {
+ _midi_source->invalidate ();
+ }
+
+ _midi_source_connections.drop_connections ();
+
_midi_source = s;
+
+ _midi_source->InterpolationChanged.connect_same_thread (
+ _midi_source_connections, boost::bind (&MidiModel::source_interpolation_changed, this, _1, _2)
+ );
+}
+
+/** The source has signalled that the interpolation style for a parameter has changed. In order to
+ * keep MidiSource and ControlList interpolation state the same, we pass this change onto the
+ * appropriate ControlList.
+ *
+ * The idea is that MidiSource and the MidiModel's ControlList states are kept in sync, and the
+ * MidiSource's InterpolationChanged signal is listened to by the GUI.
+ */
+void
+MidiModel::source_interpolation_changed (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
+{
+ Glib::Mutex::Lock lm (_control_lock);
+ control(p)->list()->set_interpolation (s);
+}
+
+/** A ControlList has signalled that its interpolation style has changed. Again, in order to keep
+ * MidiSource and ControlList interpolation state in sync, we pass this change onto our MidiSource.
+ */
+void
+MidiModel::control_list_interpolation_changed (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
+{
+ _midi_source->set_interpolation_of (p, s);
+}
+
+boost::shared_ptr<Evoral::Control>
+MidiModel::control_factory (Evoral::Parameter const & p)
+{
+ boost::shared_ptr<Evoral::Control> c = Automatable::control_factory (p);
+
+ /* Set up newly created control's lists to the appropriate interpolation state
+ from our source.
+ */
+
+ assert (_midi_source);
+
+ c->list()->set_interpolation (_midi_source->interpolation_of (p));
+
+ return c;
}