Save/Restore MIDI Automation Controls (current CC, PGM)
authorRobin Gareus <robin@gareus.org>
Wed, 7 Dec 2016 18:47:04 +0000 (19:47 +0100)
committerRobin Gareus <robin@gareus.org>
Wed, 7 Dec 2016 18:47:04 +0000 (19:47 +0100)
libs/ardour/ardour/midi_track.h
libs/ardour/midi_track.cc
libs/ardour/route.cc

index f756812e7142433f4c0a5e1d73ba42720ea22961..dc2d4ec2cf94eb4657c1d4bf4d123902e455c18c 100644 (file)
@@ -91,6 +91,7 @@ public:
                {}
 
                bool writable() const { return true; }
+               void restore_value ();
 
                MidiTrack* _route;
 
@@ -174,6 +175,7 @@ private:
 
        /** Update automation controls to reflect any changes in buffers. */
        void update_controls (const BufferSet& bufs);
+       void restore_controls ();
 };
 
 } /* namespace ARDOUR*/
index c17bc916d9cbab61842f74632dad974dadd2a0d1..c5433347a0630738547be6afbc20ab7a8f48b6eb 100644 (file)
@@ -69,12 +69,13 @@ using namespace PBD;
 
 MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
        : Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
-       , _immediate_events(1024) // FIXME: size?
+       , _immediate_events(6096) // FIXME: size?
        , _step_edit_ring_buffer(64) // FIXME: size?
        , _note_mode(Sustained)
        , _step_editing (false)
        , _input_active (true)
 {
+       _session.SessionLoaded.connect_same_thread (*this, boost::bind (&MidiTrack::restore_controls, this));
 }
 
 MidiTrack::~MidiTrack ()
@@ -266,6 +267,14 @@ MidiTrack::state(bool full_state)
        root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
        root.add_property ("input-active", (_input_active ? "yes" : "no"));
 
+       for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
+               if (boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) {
+                       boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c->second);
+                       assert (ac);
+                       root.add_child_nocopy (ac->get_state ());
+               }
+       }
+
        return root;
 }
 
@@ -334,6 +343,18 @@ MidiTrack::set_state_part_two ()
        return;
 }
 
+void
+MidiTrack::restore_controls ()
+{
+       // TODO order events (CC before PGM to set banks)
+       for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
+               boost::shared_ptr<MidiTrack::MidiControl> mctrl = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second);
+               if (mctrl) {
+                       mctrl->restore_value();
+               }
+       }
+}
+
 void
 MidiTrack::update_controls(const BufferSet& bufs)
 {
@@ -711,6 +732,12 @@ MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState st
        }
 }
 
+void
+MidiTrack::MidiControl::restore_value ()
+{
+       actually_set_value (get_value(), Controllable::NoGroup);
+}
+
 void
 MidiTrack::MidiControl::actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
 {
index 0772361e6a7a33612ea927a14a866c6f5608b482..6b16867e593155baf52ea2bc350f8e2f6be0d9c6 100644 (file)
@@ -46,6 +46,7 @@
 #include "ardour/capturing_processor.h"
 #include "ardour/debug.h"
 #include "ardour/delivery.h"
+#include "ardour/event_type_map.h"
 #include "ardour/gain_control.h"
 #include "ardour/internal_return.h"
 #include "ardour/internal_send.h"
@@ -2473,6 +2474,14 @@ Route::set_state (const XMLNode& node, int version)
                                _mute_control->set_state (*child, version);
                        } else if (prop->value() == _phase_control->name()) {
                                _phase_control->set_state (*child, version);
+                       } else {
+                               Evoral::Parameter p = EventTypeMap::instance().from_symbol (prop->value());
+                               if (p.type () >= MidiCCAutomation && p.type () < MidiSystemExclusiveAutomation) {
+                                       boost::shared_ptr<AutomationControl> ac = automation_control (p, true);
+                                       if (ac) {
+                                               ac->set_state (*child, version);
+                                       }
+                               }
                        }
                } else if (child->name() == MuteMaster::xml_node_name) {
                        _mute_master->set_state (*child, version);