summaryrefslogtreecommitdiff
path: root/libs/ardour/midi_model.cc
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2010-07-14 00:58:15 +0000
committerCarl Hetherington <carl@carlh.net>2010-07-14 00:58:15 +0000
commit593b421180290f46f39efcb21ed8192b624bbc73 (patch)
treef8a81aad5fae8683818103b192d3c53a26110728 /libs/ardour/midi_model.cc
parentb75977920e7cb02ae31bca0379dd3aa4d82f9cbc (diff)
A few fixes to interpolation of MIDI controller data. Don't interpolate
when writing these data back to a source, otherwise surprising new interpolated points appear in MIDI automation. Similarly don't interpolate when reading the model during MIDI stretch. Fix handling of interpolation state; controllers that have been set by the user to use a different interpolation style are noted in the <Source> tag of the session file and this state is sprayed around to MidiModel and the GUI as necessary. git-svn-id: svn://localhost/ardour2/branches/3.0@7409 d708f5d6-7413-0410-9779-e7cbd77b26cf
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;
}