A few fixes to interpolation of MIDI controller data. Don't interpolate
[ardour.git] / gtk2_ardour / automation_time_axis.cc
index d40f5e3405c7ca90ea92ee6891b709c8b7fdb8e2..a7114f8ff0ece3bea569cd8a5d4df8832b5cd600 100644 (file)
@@ -272,6 +272,11 @@ AutomationTimeAxisView::set_automation_state (AutoState state)
 
        if (_view) {
                _view->set_automation_state (state);
+
+               /* AutomationStreamViews don't signal when their automation state changes, so handle
+                  our updates `manually'.
+               */
+               automation_state_changed ();
        }
 }
 
@@ -282,10 +287,12 @@ AutomationTimeAxisView::automation_state_changed ()
 
        /* update button label */
 
-       if (!_line) {
-               state = Off;
-       } else {
+       if (_line) {
                state = _control->alist()->automation_state ();
+       } else if (_view) {
+               state = _view->automation_state ();
+       } else {
+               state = Off;
        }
 
        switch (state & (Off|Play|Touch|Write)) {
@@ -339,13 +346,12 @@ AutomationTimeAxisView::automation_state_changed ()
        }
 }
 
+/** The interpolation style of our AutomationList has changed, so update */
 void
-AutomationTimeAxisView::interpolation_changed ()
+AutomationTimeAxisView::interpolation_changed (AutomationList::InterpolationStyle s)
 {
-       AutomationList::InterpolationStyle style = _control->list()->interpolation();
-
        if (mode_line_item && mode_discrete_item) {
-               if (style == AutomationList::Discrete) {
+               if (s == AutomationList::Discrete) {
                        mode_discrete_item->set_active(true);
                        mode_line_item->set_active(false);
                } else {
@@ -353,38 +359,38 @@ AutomationTimeAxisView::interpolation_changed ()
                        mode_discrete_item->set_active(false);
                }
        }
-
-       if (_line) {
-               _line->set_interpolation(style);
-       }
 }
 
+/** A menu item has been selected to change our interpolation mode */
 void
 AutomationTimeAxisView::set_interpolation (AutomationList::InterpolationStyle style)
 {
-       _control->list()->set_interpolation(style);
-       if (_line) {
-               _line->set_interpolation(style);
+       /* Tell our view's list, if we have one, otherwise tell our own.
+        * Everything else will be signalled back from that.
+        */
+       
+       if (_view) {
+               _view->set_interpolation (style);
+       } else {
+               _control->list()->set_interpolation (style);
        }
 }
 
 void
 AutomationTimeAxisView::clear_clicked ()
 {
-       _session->begin_reversible_command (_("clear automation"));
        if (_line) {
+               _session->begin_reversible_command (_("clear automation"));
                _line->clear ();
        }
-       _session->commit_reversible_command ();
 }
 
 void
 AutomationTimeAxisView::set_height (uint32_t h)
 {
-       bool changed = (height != (uint32_t) h) || first_call_to_set_height;
-       bool changed_between_small_and_normal = (
-                  (height < hNormal && h >= hNormal)
-               || (height >= hNormal || h < hNormal) );
+       bool const changed = (height != (uint32_t) h) || first_call_to_set_height;
+       uint32_t const normal = preset_height (HeightNormal);
+       bool const changed_between_small_and_normal = ( (height < normal && h >= normal) || (height >= normal || h < normal) );
 
        TimeAxisView* state_parent = get_parent_with_state ();
        assert(state_parent);
@@ -411,7 +417,7 @@ AutomationTimeAxisView::set_height (uint32_t h)
 
                first_call_to_set_height = false;
 
-               if (h >= hNormal) {
+               if (h >= preset_height (HeightNormal)) {
                        controls_table.remove (name_hbox);
 
                        if (plugname) {
@@ -432,7 +438,7 @@ AutomationTimeAxisView::set_height (uint32_t h)
                        auto_button.show();
                        hide_button.show_all();
 
-               } else if (h >= hSmall) {
+               } else if (h >= preset_height (HeightSmall)) {
                        controls_table.remove (name_hbox);
                        if (plugname) {
                                if (plugname_packed) {
@@ -449,7 +455,7 @@ AutomationTimeAxisView::set_height (uint32_t h)
                        auto_button.hide();
                        hide_button.hide();
                }
-       } else if (h >= hNormal){
+       } else if (h >= preset_height (HeightNormal)) {
                cerr << "track grown, but neither changed_between_small_and_normal nor first_call_to_set_height set!" << endl;
        }
 
@@ -533,6 +539,9 @@ AutomationTimeAxisView::build_display_menu ()
 
        /* mode menu */
 
+       /* current interpolation state */
+       AutomationList::InterpolationStyle const s = _view ? _view->interpolation() : _control->list()->interpolation ();
+
        if (EventTypeMap::instance().is_midi_parameter(_control->parameter())) {
 
                Menu* auto_mode_menu = manage (new Menu);
@@ -545,17 +554,13 @@ AutomationTimeAxisView::build_display_menu ()
                                sigc::mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
                                AutomationList::Discrete)));
                mode_discrete_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
-               mode_discrete_item->set_active(_control->list()->interpolation() == AutomationList::Discrete);
+               mode_discrete_item->set_active (s == AutomationList::Discrete);
 
                am_items.push_back (RadioMenuElem (group, _("Linear"), sigc::bind (
                                sigc::mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
                                AutomationList::Linear)));
                mode_line_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
-
-               // Set default interpolation type to linear if this isn't a (usually) discrete controller
-               if (EventTypeMap::instance().interpolation_of(_control->parameter()) == Evoral::ControlList::Linear) {
-                       mode_line_item->set_active(_control->list()->interpolation() == AutomationList::Linear);
-               }
+               mode_line_item->set_active (s == AutomationList::Linear);
 
                items.push_back (MenuElem (_("Mode"), *auto_mode_menu));
        }
@@ -563,7 +568,7 @@ AutomationTimeAxisView::build_display_menu ()
        /* make sure the automation menu state is correct */
 
        automation_state_changed ();
-       interpolation_changed ();
+       interpolation_changed (s);
 }
 
 void
@@ -821,7 +826,7 @@ void
 AutomationTimeAxisView::clear_lines ()
 {
        _line.reset();
-       automation_connection.disconnect ();
+       _list_connections.drop_connections ();
 }
 
 void
@@ -831,7 +836,13 @@ AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
        assert(!_line);
        assert(line->the_list() == _control->list());
 
-       _control->alist()->automation_state_changed.connect (automation_connection, invalidator (*this), boost::bind (&AutomationTimeAxisView::automation_state_changed, this), gui_context());
+       _control->alist()->automation_state_changed.connect (
+               _list_connections, invalidator (*this), boost::bind (&AutomationTimeAxisView::automation_state_changed, this), gui_context()
+               );
+       
+       _control->alist()->InterpolationChanged.connect (
+               _list_connections, invalidator (*this), boost::bind (&AutomationTimeAxisView::interpolation_changed, this, _1), gui_context()
+               );
 
        _line = line;
        //_controller = AutomationController::create(_session, line->the_list(), _control);
@@ -935,3 +946,10 @@ AutomationTimeAxisView::set_visibility (bool yn)
 
        return changed;
 }
+
+/** @return true if this view has any automation data to display */
+bool
+AutomationTimeAxisView::has_automation () const
+{
+       return ( (_line && _line->npoints() > 0) || (_view && _view->has_automation()) );
+}