Preferences/Config changes for image-surface settings
[ardour.git] / gtk2_ardour / automation_line.cc
index 9c1aa13198bc52c76dfbb2b9595d5c7491cad4ed..34d59ef581689e8047669c1f4903db0c419fc770 100644 (file)
@@ -1,21 +1,28 @@
 /*
-    Copyright (C) 2002-2003 Paul Davis
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
+ * Copyright (C) 2005-2017 Paul Davis <paul@linuxaudiosystems.com>
+ * Copyright (C) 2005 Karsten Wiese <fzuuzf@googlemail.com>
+ * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
+ * Copyright (C) 2006 Hans Fugal <hans@fugal.net>
+ * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
+ * Copyright (C) 2007-2015 David Robillard <d@drobilla.net>
+ * Copyright (C) 2007 Doug McLain <doug@nostar.net>
+ * Copyright (C) 2013-2017 Robin Gareus <robin@gareus.org>
+ * Copyright (C) 2014-2016 Nick Mainsbridge <mainsbridge@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
 
 #include <cmath>
 
@@ -44,7 +51,7 @@
 #include "ardour/parameter_types.h"
 #include "ardour/tempo.h"
 
-#include "evoral/Curve.hpp"
+#include "evoral/Curve.h"
 
 #include "canvas/debug.h"
 
@@ -70,7 +77,7 @@ using namespace ARDOUR;
 using namespace PBD;
 using namespace Editing;
 
-/** @param converter A TimeConverter whose origin_b is the start time of the AutomationList in session frames.
+/** @param converter A TimeConverter whose origin_b is the start time of the AutomationList in session samples.
  *  This will not be deleted by AutomationLine.
  */
 AutomationLine::AutomationLine (const string&                              name,
@@ -78,14 +85,14 @@ AutomationLine::AutomationLine (const string&                              name,
                                 ArdourCanvas::Item&                        parent,
                                 boost::shared_ptr<AutomationList>          al,
                                 const ParameterDescriptor&                 desc,
-                                Evoral::TimeConverter<double, framepos_t>* converter)
+                                Evoral::TimeConverter<double, samplepos_t>* converter)
        : trackview (tv)
        , _name (name)
        , alist (al)
-       , _time_converter (converter ? converter : new Evoral::IdentityConverter<double, framepos_t>)
+       , _time_converter (converter ? converter : new Evoral::IdentityConverter<double, samplepos_t>)
        , _parent_group (parent)
        , _offset (0)
-       , _maximum_time (max_framepos)
+       , _maximum_time (max_samplepos)
        , _fill (false)
        , _desc (desc)
 {
@@ -194,6 +201,7 @@ AutomationLine::get_uses_gain_mapping () const
 {
        switch (_desc.type) {
                case GainAutomation:
+               case BusSendLevel:
                case EnvelopeAutomation:
                case TrimAutomation:
                        return true;
@@ -250,7 +258,7 @@ AutomationLine::set_line_color (uint32_t color)
        _line_color = color;
        line->set_outline_color (color);
 
-       ArdourCanvas::SVAModifier mod = UIConfiguration::instance().modifier ("automation line fill");
+       Gtkmm2ext::SVAModifier mod = UIConfiguration::instance().modifier ("automation line fill");
 
        line->set_fill_color ((color & 0xffffff00) + mod.a()*255);
 }
@@ -382,6 +390,7 @@ AutomationLine::string_to_fraction (string const & s) const
 
        switch (_desc.type) {
                case GainAutomation:
+               case BusSendLevel:
                case EnvelopeAutomation:
                case TrimAutomation:
                        if (s == "-inf") { /* translation */
@@ -488,9 +497,9 @@ AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e)
                if (front()->view_index() > 0) {
                        before_x = line.nth (front()->view_index() - 1)->get_x();
 
-                       const framepos_t pos = e.pixel_to_sample(before_x);
-                       const Meter& meter = map.meter_at_frame (pos);
-                       const framecnt_t len = ceil (meter.frames_per_bar (map.tempo_at_frame (pos), e.session()->frame_rate())
+                       const samplepos_t pos = e.pixel_to_sample(before_x);
+                       const Meter& meter = map.meter_at_sample (pos);
+                       const samplecnt_t len = ceil (meter.samples_per_bar (map.tempo_at_sample (pos), e.session()->sample_rate())
                                        / (Timecode::BBT_Time::ticks_per_beat * meter.divisions_per_bar()) );
                        const double one_tick_in_pixels = e.sample_to_pixel_unrounded (len);
 
@@ -504,9 +513,9 @@ AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e)
                if (back()->view_index() < (line.npoints() - 1)) {
                        after_x = line.nth (back()->view_index() + 1)->get_x();
 
-                       const framepos_t pos = e.pixel_to_sample(after_x);
-                       const Meter& meter = map.meter_at_frame (pos);
-                       const framecnt_t len = ceil (meter.frames_per_bar (map.tempo_at_frame (pos), e.session()->frame_rate())
+                       const samplepos_t pos = e.pixel_to_sample(after_x);
+                       const Meter& meter = map.meter_at_sample (pos);
+                       const samplecnt_t len = ceil (meter.samples_per_bar (map.tempo_at_sample (pos), e.session()->sample_rate())
                                        / (Timecode::BBT_Time::ticks_per_beat * meter.divisions_per_bar()));
                        const double one_tick_in_pixels = e.sample_to_pixel_unrounded (len);
 
@@ -872,14 +881,14 @@ AutomationLine::remove_point (ControlPoint& cp)
 }
 
 /** Get selectable points within an area.
- *  @param start Start position in session frames.
- *  @param end End position in session frames.
+ *  @param start Start position in session samples.
+ *  @param end End position in session samples.
  *  @param bot Bottom y range, as a fraction of line height, where 0 is the bottom of the line.
  *  @param top Top y range, as a fraction of line height, where 0 is the bottom of the line.
  *  @param result Filled in with selectable things; in this case, ControlPoints.
  */
 void
-AutomationLine::get_selectables (framepos_t start, framepos_t end, double botfrac, double topfrac, list<Selectable*>& results)
+AutomationLine::get_selectables (samplepos_t start, samplepos_t end, double botfrac, double topfrac, list<Selectable*>& results)
 {
        /* convert fractions to display coordinates with 0 at the top of the track */
        double const bot_track = (1 - topfrac) * trackview.current_height ();
@@ -889,12 +898,12 @@ AutomationLine::get_selectables (framepos_t start, framepos_t end, double botfra
                double const model_when = (*(*i)->model())->when;
 
                /* model_when is relative to the start of the source, so we just need to add on the origin_b here
-                  (as it is the session frame position of the start of the source)
+                  (as it is the session sample position of the start of the source)
                */
 
-               framepos_t const session_frames_when = _time_converter->to (model_when) + _time_converter->origin_b ();
+               samplepos_t const session_samples_when = _time_converter->to (model_when) + _time_converter->origin_b ();
 
-               if (session_frames_when >= start && session_frames_when <= end && (*i)->get_y() >= bot_track && (*i)->get_y() <= top_track) {
+               if (session_samples_when >= start && session_samples_when <= end && (*i)->get_y() >= bot_track && (*i)->get_y() <= top_track) {
                        results.push_back (*i);
                }
        }
@@ -988,7 +997,7 @@ AutomationLine::reset_callback (const Evoral::ControlList& events)
                        continue;
                }
 
-               if (tx >= max_framepos || tx < 0 || tx >= _maximum_time) {
+               if (tx >= max_samplepos || tx < 0 || tx >= _maximum_time) {
                        continue;
                }
 
@@ -1056,14 +1065,21 @@ AutomationLine::reset ()
                return;
        }
 
+       /* TODO: abort any drags in progress, e.g. draging points while writing automation
+        * (the control-point model, used by AutomationLine::drag_motion, will be invalid).
+        *
+        * Note: reset() may also be called from an aborted drag (LineDrag::aborted)
+        * maybe abort in list_changed(), interpolation_changed() and ... ?
+        * XXX
+        */
+
        alist->apply_to_points (*this, &AutomationLine::reset_callback);
 }
 
 void
 AutomationLine::queue_reset ()
 {
-       /* this must be called from the GUI thread
-        */
+       /* this must be called from the GUI thread */
 
        if (trackview.editor().session()->transport_rolling() && alist->automation_write()) {
                /* automation write pass ... defer to a timeout */
@@ -1168,18 +1184,24 @@ AutomationLine::view_to_model_coord (double& x, double& y) const
 void
 AutomationLine::view_to_model_coord_y (double& y) const
 {
-#ifdef XXX_NEW_INTERPOLATON__BREAK_SESSION_FORMAT_XXX
        if (alist->default_interpolation () != alist->interpolation()) {
                switch (alist->interpolation()) {
+                       case AutomationList::Discrete:
+                               /* toggles and MIDI only -- see is_stepped() */
+                               assert (alist->default_interpolation () == AutomationList::Linear);
+                               break;
                        case AutomationList::Linear:
                                y = y * (_desc.upper - _desc.lower) + _desc.lower;
                                return;
                        default:
+                               /* types that default to linear, can't be use
+                                * Logarithmic or Exponential interpolation.
+                                * "Curved" is invalid for automation (only x-fads)
+                                */
                                assert (0);
                                break;
                }
        }
-#endif
        y = _desc.from_interface (y);
 }
 
@@ -1204,18 +1226,24 @@ AutomationLine::apply_delta (double& val, double delta) const
 void
 AutomationLine::model_to_view_coord_y (double& y) const
 {
-#ifdef XXX_NEW_INTERPOLATON__BREAK_SESSION_FORMAT_XXX
        if (alist->default_interpolation () != alist->interpolation()) {
                switch (alist->interpolation()) {
+                       case AutomationList::Discrete:
+                               /* toggles and MIDI only -- see is_stepped */
+                               assert (alist->default_interpolation () == AutomationList::Linear);
+                               break;
                        case AutomationList::Linear:
                                y = (y - _desc.lower) / (_desc.upper - _desc.lower);
                                return;
                        default:
+                               /* types that default to linear, can't be use
+                                * Logarithmic or Exponential interpolation.
+                                * "Curved" is invalid for automation (only x-fads)
+                                */
                                assert (0);
                                break;
                }
        }
-#endif
        y = _desc.to_interface (y);
 }
 
@@ -1304,7 +1332,7 @@ AutomationLine::memento_command_binder ()
  *  to the start of the track or region that it is on.
  */
 void
-AutomationLine::set_maximum_time (framecnt_t t)
+AutomationLine::set_maximum_time (samplecnt_t t)
 {
        if (_maximum_time == t) {
                return;
@@ -1315,11 +1343,11 @@ AutomationLine::set_maximum_time (framecnt_t t)
 }
 
 
-/** @return min and max x positions of points that are in the list, in session frames */
-pair<framepos_t, framepos_t>
+/** @return min and max x positions of points that are in the list, in session samples */
+pair<samplepos_t, samplepos_t>
 AutomationLine::get_point_x_range () const
 {
-       pair<framepos_t, framepos_t> r (max_framepos, 0);
+       pair<samplepos_t, samplepos_t> r (max_samplepos, 0);
 
        for (AutomationList::const_iterator i = the_list()->begin(); i != the_list()->end(); ++i) {
                r.first = min (r.first, session_position (i));
@@ -1329,14 +1357,14 @@ AutomationLine::get_point_x_range () const
        return r;
 }
 
-framepos_t
+samplepos_t
 AutomationLine::session_position (AutomationList::const_iterator p) const
 {
        return _time_converter->to ((*p)->when) + _offset + _time_converter->origin_b ();
 }
 
 void
-AutomationLine::set_offset (framepos_t off)
+AutomationLine::set_offset (samplepos_t off)
 {
        if (_offset == off) {
                return;