+ _controllable->start_touch (_controllable->session().transport_frame());
+ StartGesture.emit(); /* EMIT SIGNAL */
+}
+
+void
+AutomationController::end_touch ()
+{
+ if (_controllable->automation_state() == Touch) {
+
+ bool mark = false;
+ double when = 0;
+
+ if (_controllable->session().transport_rolling()) {
+ mark = true;
+ when = _controllable->session().transport_frame();
+ }
+
+ _controllable->stop_touch (mark, when);
+ }
+ StopGesture.emit(); /* EMIT SIGNAL */
+}
+
+void
+AutomationController::toggled ()
+{
+ ArdourButton* but = dynamic_cast<ArdourButton*>(_widget);
+ if (but) {
+ if (_controllable->session().transport_rolling()) {
+ if (_controllable->automation_state() == Touch) {
+ _controllable->set_automation_state(Write);
+ }
+ if (_controllable->list()) {
+ _controllable->list()->set_in_write_pass(true, false, _controllable->session().audible_frame());
+ }
+ }
+ const bool was_active = _controllable->get_value() >= 0.5;
+ if (was_active && but->get_active()) {
+ _adjustment->set_value(0.0);
+ but->set_active(false);
+ } else if (!was_active && !but->get_active()) {
+ _adjustment->set_value(1.0);
+ but->set_active(true);
+ }
+ }
+}
+
+static double
+midi_note_to_hz(int note)
+{
+ const double tuning = 440.0;
+ return tuning * pow(2, (note - 69.0) / 12.0);
+}
+
+static double
+clamp(double val, double min, double max)
+{
+ if (val < min) {
+ return min;
+ } else if (val > max) {
+ return max;
+ }
+ return val;
+}
+
+void
+AutomationController::run_note_select_dialog()
+{
+ const ARDOUR::ParameterDescriptor& desc = _controllable->desc();
+ NoteSelectDialog* dialog = new NoteSelectDialog();
+ if (dialog->run() == Gtk::RESPONSE_ACCEPT) {
+ const double value = ((_controllable->desc().unit == ARDOUR::ParameterDescriptor::HZ)
+ ? midi_note_to_hz(dialog->note_number())
+ : dialog->note_number());
+ _controllable->set_value(clamp(value, desc.lower, desc.upper));
+ }
+ delete dialog;