X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fautomation_line.cc;h=cf7e10dd8a49efc202e065217bcdc813bc3bd81d;hb=baf8f379677d6fea53d665aaff1945ccd896a6fe;hp=43245f58d8afb03f1366154e1e4ef780a74429cb;hpb=91fac4c96dc6210dcc056da70dc608700d7eb570;p=ardour.git diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index 43245f58d8..cf7e10dd8a 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -30,7 +30,6 @@ #include #include -#include #include "boost/shared_ptr.hpp" @@ -53,12 +52,12 @@ #include "control_point.h" #include "gui_thread.h" #include "rgb_macros.h" -#include "ardour_ui.h" #include "public_editor.h" #include "selection.h" #include "time_axis_view.h" #include "point_selection.h" #include "automation_time_axis.h" +#include "ui_config.h" #include "ardour/event_type_map.h" #include "ardour/session.h" @@ -94,7 +93,7 @@ AutomationLine::AutomationLine (const string& name, } else { _our_time_converter = true; } - + _visible = Line; update_pending = false; @@ -119,8 +118,8 @@ AutomationLine::AutomationLine (const string& name, trackview.session()->register_with_memento_command_factory(alist->id(), this); if (alist->parameter().type() == GainAutomation || - alist->parameter().type() == EnvelopeAutomation || - desc.unit == ParameterDescriptor::DB) { + alist->parameter().type() == TrimAutomation || + alist->parameter().type() == EnvelopeAutomation) { set_uses_gain_mapping (true); } @@ -201,9 +200,9 @@ void AutomationLine::hide () { /* leave control points setting unchanged, we are just hiding the - overall line + overall line */ - + set_visibility (AutomationLine::VisibleAspects (_visible & ~Line)); } @@ -375,10 +374,16 @@ AutomationLine::fraction_to_string (double fraction) const { if (_uses_gain_mapping) { char buf[32]; - if (fraction == 0.0) { - snprintf (buf, sizeof (buf), "-inf"); + if (_desc.type == GainAutomation || _desc.type == EnvelopeAutomation || _desc.lower == 0) { + if (fraction == 0.0) { + snprintf (buf, sizeof (buf), "-inf"); + } else { + snprintf (buf, sizeof (buf), "%.1f", accurate_coefficient_to_dB (slider_position_to_gain_with_max (fraction, _desc.upper))); + } } else { - snprintf (buf, sizeof (buf), "%.1f", accurate_coefficient_to_dB (slider_position_to_gain_with_max (fraction, Config->get_max_gain()))); + const double lower_db = accurate_coefficient_to_dB (_desc.lower); + const double range_db = accurate_coefficient_to_dB (_desc.upper) - lower_db; + snprintf (buf, sizeof (buf), "%.1f", lower_db + fraction * range_db); } return buf; } else { @@ -459,7 +464,6 @@ AutomationLine::string_to_fraction (string const & s) const void AutomationLine::start_drag_single (ControlPoint* cp, double x, float fraction) { - trackview.editor().begin_reversible_command (_("automation event move")); trackview.editor().session()->add_command ( new MementoCommand (memento_command_binder(), &get_state(), 0)); @@ -485,7 +489,6 @@ AutomationLine::start_drag_single (ControlPoint* cp, double x, float fraction) void AutomationLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction) { - trackview.editor().begin_reversible_command (_("automation range move")); trackview.editor().session()->add_command ( new MementoCommand (memento_command_binder (), &get_state(), 0)); @@ -505,7 +508,6 @@ AutomationLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction) void AutomationLine::start_drag_multiple (list cp, float fraction, XMLNode* state) { - trackview.editor().begin_reversible_command (_("automation range move")); trackview.editor().session()->add_command ( new MementoCommand (memento_command_binder(), state, 0)); @@ -518,13 +520,13 @@ struct ControlPointSorter bool operator() (ControlPoint const * a, ControlPoint const * b) const { if (floateq (a->get_x(), b->get_x(), 1)) { return a->view_index() < b->view_index(); - } + } return a->get_x() < b->get_x(); } }; AutomationLine::ContiguousControlPoints::ContiguousControlPoints (AutomationLine& al) - : line (al), before_x (0), after_x (DBL_MAX) + : line (al), before_x (0), after_x (DBL_MAX) { } @@ -536,7 +538,7 @@ AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e) if (sz > 0 && sz < line.npoints()) { const TempoMap& map (e.session()->tempo_map()); - /* determine the limits on x-axis motion for this + /* determine the limits on x-axis motion for this contiguous range of control points */ @@ -544,8 +546,8 @@ AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e) 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 (pos); - const framecnt_t len = ceil (meter.frames_per_bar (map.tempo_at (pos), e.session()->frame_rate()) + 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()) / (Timecode::BBT_Time::ticks_per_beat * meter.divisions_per_bar()) ); const double one_tick_in_pixels = e.sample_to_pixel_unrounded (len); @@ -560,8 +562,8 @@ AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e) 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 (pos); - const framecnt_t len = ceil (meter.frames_per_bar (map.tempo_at (pos), e.session()->frame_rate()) + 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()) / (Timecode::BBT_Time::ticks_per_beat * meter.divisions_per_bar())); const double one_tick_in_pixels = e.sample_to_pixel_unrounded (len); @@ -570,8 +572,8 @@ AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e) } } -double -AutomationLine::ContiguousControlPoints::clamp_dx (double dx) +double +AutomationLine::ContiguousControlPoints::clamp_dx (double dx) { if (empty()) { return dx; @@ -579,10 +581,10 @@ AutomationLine::ContiguousControlPoints::clamp_dx (double dx) /* get the maximum distance we can move any of these points along the x-axis */ - + double tx; /* possible position a point would move to, given dx */ ControlPoint* cp; - + if (dx > 0) { /* check the last point, since we're moving later in time */ cp = back(); @@ -591,14 +593,14 @@ AutomationLine::ContiguousControlPoints::clamp_dx (double dx) cp = front(); } - tx = cp->get_x() + dx; // new possible position if we just add the motion + tx = cp->get_x() + dx; // new possible position if we just add the motion tx = max (tx, before_x); // can't move later than following point tx = min (tx, after_x); // can't move earlier than preceeding point - return tx - cp->get_x (); + return tx - cp->get_x (); } -void -AutomationLine::ContiguousControlPoints::move (double dx, double dy) +void +AutomationLine::ContiguousControlPoints::move (double dx, double dy) { for (std::list::iterator i = begin(); i != end(); ++i) { (*i)->move_to ((*i)->get_x() + dx, (*i)->get_y() - line.height() * dy, ControlPoint::Full); @@ -642,19 +644,19 @@ AutomationLine::drag_motion (double const x, float fraction, bool ignore_x, bool if (!_drag_had_movement) { - /* "first move" ... do some stuff that we don't want to do if + /* "first move" ... do some stuff that we don't want to do if no motion ever took place, but need to do before we handle motion. */ - + /* partition the points we are dragging into (potentially several) * set(s) of contiguous points. this will not happen with a normal * drag, but if the user does a discontiguous selection, it can. */ - + uint32_t expected_view_index = 0; CCP contig; - + for (list::iterator i = _drag_points.begin(); i != _drag_points.end(); ++i) { if (i == _drag_points.begin() || (*i)->view_index() != expected_view_index) { contig.reset (new ContiguousControlPoints (*this)); @@ -671,13 +673,14 @@ AutomationLine::drag_motion (double const x, float fraction, bool ignore_x, bool for (vector::iterator ccp = contiguous_points.begin(); ccp != contiguous_points.end(); ++ccp) { (*ccp)->compute_x_bounds (trackview.editor()); } - } + _drag_had_movement = true; + } /* OK, now on to the stuff related to *this* motion event. First, for * each contiguous range, figure out the maximum x-axis motion we are * allowed (because of neighbouring points that are not moving. - * - * if we are moving forwards with push, we don't need to do this, + * + * if we are moving forwards with push, we don't need to do this, * since all later points will move too. */ @@ -691,7 +694,6 @@ AutomationLine::drag_motion (double const x, float fraction, bool ignore_x, bool } /* clamp y */ - for (list::iterator i = _drag_points.begin(); i != _drag_points.end(); ++i) { double const y = ((_height - (*i)->get_y()) / _height) + dy; if (y < 0) { @@ -705,7 +707,7 @@ AutomationLine::drag_motion (double const x, float fraction, bool ignore_x, bool if (dx || dy) { /* and now move each section */ - + for (vector::iterator ccp = contiguous_points.begin(); ccp != contiguous_points.end(); ++ccp) { (*ccp)->move (dx, dy); } @@ -727,14 +729,13 @@ AutomationLine::drag_motion (double const x, float fraction, bool ignore_x, bool line->set_steps (line_points, is_stepped()); } } - + double const result_frac = _last_drag_fraction + dy; _drag_distance += dx; _drag_x += dx; - _last_drag_fraction = fraction; - _drag_had_movement = true; + _last_drag_fraction = result_frac; did_push = with_push; - return pair (_drag_x + dx, _last_drag_fraction + dy); + return pair (_drag_x + dx, result_frac); } /** Should be called to indicate the end of a drag */ @@ -880,8 +881,9 @@ AutomationLine::remove_point (ControlPoint& cp) trackview.editor().begin_reversible_command (_("remove control point")); XMLNode &before = alist->get_state(); + trackview.editor ().get_selection ().clear_points (); alist->erase (cp.model()); - + trackview.editor().session()->add_command( new MementoCommand (memento_command_binder (), &before, &alist->get_state())); @@ -909,7 +911,7 @@ AutomationLine::get_selectables (framepos_t start, framepos_t end, double botfra /* 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) */ - + framepos_t const session_frames_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) { @@ -944,9 +946,10 @@ AutomationLine::set_selected_points (PointSelection const & points) set_colors (); } -void AutomationLine::set_colors () +void +AutomationLine::set_colors () { - set_line_color (ARDOUR_UI::config()->color ("automation line")); + set_line_color (UIConfiguration::instance().color ("automation line")); for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { (*i)->set_color (); } @@ -989,7 +992,7 @@ AutomationLine::reset_callback (const Evoral::ControlList& events) np = events.size(); Evoral::ControlList& e = const_cast (events); - + for (AutomationList::iterator ai = e.begin(); ai != e.end(); ++ai, ++pi) { double tx = (*ai)->when; @@ -1004,17 +1007,17 @@ AutomationLine::reset_callback (const Evoral::ControlList& events) _name) << endmsg; continue; } - + if (tx >= max_framepos || tx < 0 || tx >= _maximum_time) { continue; } - + /* convert x-coordinate to a canvas unit coordinate (this takes * zoom and scroll into account). */ - + tx = trackview.editor().sample_to_pixel_unrounded (tx); - + /* convert from canonical view height (0..1.0) to actual * height coordinates (using X11's top-left rooted system) */ @@ -1185,12 +1188,22 @@ AutomationLine::view_to_model_coord (double& x, double& y) const void AutomationLine::view_to_model_coord_y (double& y) const { - /* TODO: This should be more generic (use ParameterDescriptor) */ - if (alist->parameter().type() == GainAutomation || - alist->parameter().type() == EnvelopeAutomation) { - y = slider_position_to_gain_with_max (y, Config->get_max_gain()); + /* TODO: This should be more generic (use ParameterDescriptor) + * or better yet: Controllable -> set_interface(); + */ + if ( alist->parameter().type() == GainAutomation + || alist->parameter().type() == EnvelopeAutomation + || (_desc.logarithmic && _desc.lower == 0. && _desc.upper > _desc.lower)) { + y = slider_position_to_gain_with_max (y, _desc.upper); + y = max ((double)_desc.lower, y); + y = min ((double)_desc.upper, y); + } else if (alist->parameter().type() == TrimAutomation + || (_desc.logarithmic && _desc.lower * _desc.upper > 0 && _desc.upper > _desc.lower)) { + const double lower_db = accurate_coefficient_to_dB (_desc.lower); + const double range_db = accurate_coefficient_to_dB (_desc.upper) - lower_db; y = max (0.0, y); - y = min (2.0, y); + y = min (1.0, y); + y = dB_to_coefficient (lower_db + y * range_db); } else if (alist->parameter().type() == PanAzimuthAutomation || alist->parameter().type() == PanElevationAutomation) { y = 1.0 - y; @@ -1210,9 +1223,15 @@ void AutomationLine::model_to_view_coord_y (double& y) const { /* TODO: This should be more generic (use ParameterDescriptor) */ - if (alist->parameter().type() == GainAutomation || - alist->parameter().type() == EnvelopeAutomation) { - y = gain_to_slider_position_with_max (y, Config->get_max_gain()); + if ( alist->parameter().type() == GainAutomation + || alist->parameter().type() == EnvelopeAutomation + || (_desc.logarithmic && _desc.lower == 0. && _desc.upper > _desc.lower)) { + y = gain_to_slider_position_with_max (y, _desc.upper); + } else if (alist->parameter().type() == TrimAutomation + || (_desc.logarithmic && _desc.lower * _desc.upper > 0 && _desc.upper > _desc.lower)) { + const double lower_db = accurate_coefficient_to_dB (_desc.lower); + const double range_db = accurate_coefficient_to_dB (_desc.upper) - lower_db; + y = (accurate_coefficient_to_dB (y) - lower_db) / range_db; } else if (alist->parameter().type() == PanAzimuthAutomation || alist->parameter().type() == PanElevationAutomation) { y = 1.0 - y; @@ -1240,7 +1259,7 @@ AutomationLine::interpolation_changed (AutomationList::InterpolationStyle style) } void -AutomationLine::add_visible_control_point (uint32_t view_index, uint32_t pi, double tx, double ty, +AutomationLine::add_visible_control_point (uint32_t view_index, uint32_t pi, double tx, double ty, AutomationList::iterator model, uint32_t npoints) { ControlPoint::ShapeType shape;