+ Processor::set_state (node, version);
+
+ if ((gain_node = node.child (Controllable::xml_node_name.c_str())) != 0) {
+ _gain_control->set_state (*gain_node, version);
+ }
+
+ return 0;
+}
+
+/** Write gain automation for this cycle into the buffer previously passed in to
+ * set_gain_automation_buffer (if we are in automation playback mode and the
+ * transport is rolling).
+ */
+void
+Amp::setup_gain_automation (framepos_t start_frame, framepos_t end_frame, framecnt_t nframes)
+{
+ Glib::Threads::Mutex::Lock am (control_lock(), Glib::Threads::TRY_LOCK);
+
+ if (am.locked()
+ && (_session.transport_rolling() || _session.bounce_processing())
+ && _gain_control->automation_playback())
+ {
+ assert (_gain_automation_buffer);
+ _apply_gain_automation = _gain_control->list()->curve().rt_safe_get_vector (
+ start_frame, end_frame, _gain_automation_buffer, nframes);
+ if (start_frame != _current_automation_frame && _session.bounce_processing ()) {
+ _current_gain = _gain_automation_buffer[0];
+ }
+ _current_automation_frame = end_frame;
+ } else {
+ _apply_gain_automation = false;
+ _current_automation_frame = INT64_MAX;
+ }
+}
+
+bool
+Amp::visible() const
+{
+ return true;
+}
+
+std::string
+Amp::value_as_string (boost::shared_ptr<const AutomationControl> ac) const
+{
+ if (ac == _gain_control) {
+ char buffer[32];
+ snprintf (buffer, sizeof (buffer), _("%.2fdB"), ac->internal_to_user (ac->get_value ()));
+ return buffer;
+ }
+
+ return Automatable::value_as_string (ac);
+}
+
+/** Sets up the buffer that setup_gain_automation and ::run will use for
+ * gain automationc curves. Must be called before setup_gain_automation,
+ * and must be called with process lock held.
+ */
+
+void
+Amp::set_gain_automation_buffer (gain_t* g)
+{
+ _gain_automation_buffer = g;
+}