mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-12 01:26:31 +01:00
Implement #826: edit-click on automation points allows value edit.
git-svn-id: svn://localhost/ardour2/branches/3.0@4329 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
058e7f2c01
commit
883eeb8cf2
7 changed files with 137 additions and 29 deletions
|
|
@ -137,6 +137,7 @@ canvas-simpleline.c
|
||||||
canvas-simplerect.c
|
canvas-simplerect.c
|
||||||
canvas-waveview.c
|
canvas-waveview.c
|
||||||
control_point.cc
|
control_point.cc
|
||||||
|
control_point_dialog.cc
|
||||||
crossfade_edit.cc
|
crossfade_edit.cc
|
||||||
crossfade_view.cc
|
crossfade_view.cc
|
||||||
curvetest.cc
|
curvetest.cc
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ AutomationLine::AutomationLine (const string& name, TimeAxisView& tv, ArdourCanv
|
||||||
_interpolation = al->interpolation();
|
_interpolation = al->interpolation();
|
||||||
points_visible = false;
|
points_visible = false;
|
||||||
update_pending = false;
|
update_pending = false;
|
||||||
_vc_uses_gain_mapping = false;
|
_uses_gain_mapping = false;
|
||||||
no_draw = false;
|
no_draw = false;
|
||||||
_visible = true;
|
_visible = true;
|
||||||
terminal_points_can_slide = true;
|
terminal_points_can_slide = true;
|
||||||
|
|
@ -84,8 +84,9 @@ AutomationLine::AutomationLine (const string& name, TimeAxisView& tv, ArdourCanv
|
||||||
|
|
||||||
trackview.session().register_with_memento_command_factory(alist->id(), this);
|
trackview.session().register_with_memento_command_factory(alist->id(), this);
|
||||||
|
|
||||||
if (alist->parameter().type() == GainAutomation)
|
if (alist->parameter().type() == GainAutomation) {
|
||||||
set_verbose_cursor_uses_gain_mapping (true);
|
set_uses_gain_mapping (true);
|
||||||
|
}
|
||||||
|
|
||||||
set_interpolation(alist->interpolation());
|
set_interpolation(alist->interpolation());
|
||||||
}
|
}
|
||||||
|
|
@ -176,10 +177,10 @@ AutomationLine::set_line_color (uint32_t color)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AutomationLine::set_verbose_cursor_uses_gain_mapping (bool yn)
|
AutomationLine::set_uses_gain_mapping (bool yn)
|
||||||
{
|
{
|
||||||
if (yn != _vc_uses_gain_mapping) {
|
if (yn != _uses_gain_mapping) {
|
||||||
_vc_uses_gain_mapping = yn;
|
_uses_gain_mapping = yn;
|
||||||
reset ();
|
reset ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -194,6 +195,41 @@ AutomationLine::nth (uint32_t n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AutomationLine::modify_point_y (ControlPoint& cp, double y)
|
||||||
|
{
|
||||||
|
/* clamp y-coord appropriately. y is supposed to be a normalized fraction (0.0-1.0),
|
||||||
|
and needs to be converted to a canvas unit distance.
|
||||||
|
*/
|
||||||
|
|
||||||
|
y = max (0.0, y);
|
||||||
|
y = min (1.0, y);
|
||||||
|
y = _height - (y * _height);
|
||||||
|
|
||||||
|
double const x = trackview.editor.frame_to_unit ((*cp.model())->when);
|
||||||
|
|
||||||
|
trackview.editor.current_session()->begin_reversible_command (_("automation event move"));
|
||||||
|
trackview.editor.current_session()->add_command (new MementoCommand<AutomationList>(*alist.get(), &get_state(), 0));
|
||||||
|
|
||||||
|
cp.move_to (x, y, ControlPoint::Full);
|
||||||
|
reset_line_coords (cp);
|
||||||
|
|
||||||
|
if (line_points.size() > 1) {
|
||||||
|
line->property_points() = line_points;
|
||||||
|
}
|
||||||
|
|
||||||
|
alist->freeze ();
|
||||||
|
sync_model_with_view_point (cp, false, 0);
|
||||||
|
alist->thaw ();
|
||||||
|
|
||||||
|
update_pending = false;
|
||||||
|
|
||||||
|
trackview.editor.current_session()->add_command (new MementoCommand<AutomationList>(*alist.get(), 0, &alist->get_state()));
|
||||||
|
trackview.editor.current_session()->commit_reversible_command ();
|
||||||
|
trackview.editor.current_session()->set_dirty ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool with_push)
|
AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool with_push)
|
||||||
{
|
{
|
||||||
|
|
@ -602,15 +638,31 @@ AutomationLine::determine_visible_control_points (ALPoints& points)
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
string
|
||||||
AutomationLine::get_verbose_cursor_string (double fraction)
|
AutomationLine::get_verbose_cursor_string (double fraction) const
|
||||||
|
{
|
||||||
|
std::string s = fraction_to_string (fraction);
|
||||||
|
if (_uses_gain_mapping) {
|
||||||
|
s += " dB";
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param fraction y fraction
|
||||||
|
* @return string representation of this value, using dB if appropriate.
|
||||||
|
*/
|
||||||
|
|
||||||
|
string
|
||||||
|
AutomationLine::fraction_to_string (double fraction) const
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
if (_vc_uses_gain_mapping) {
|
if (_uses_gain_mapping) {
|
||||||
if (fraction == 0.0) {
|
if (fraction == 0.0) {
|
||||||
snprintf (buf, sizeof (buf), "-inf dB");
|
snprintf (buf, sizeof (buf), "-inf");
|
||||||
} else {
|
} else {
|
||||||
snprintf (buf, sizeof (buf), "%.1fdB", coefficient_to_dB (slider_position_to_gain (fraction)));
|
snprintf (buf, sizeof (buf), "%.1f", coefficient_to_dB (slider_position_to_gain (fraction)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
view_to_model_y (fraction);
|
view_to_model_y (fraction);
|
||||||
|
|
@ -624,6 +676,31 @@ AutomationLine::get_verbose_cursor_string (double fraction)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param s Value string in the form as returned by fraction_to_string.
|
||||||
|
* @return Corresponding y fraction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
double
|
||||||
|
AutomationLine::string_to_fraction (string const & s) const
|
||||||
|
{
|
||||||
|
if (s == "-inf") {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double v;
|
||||||
|
sscanf (s.c_str(), "%lf", &v);
|
||||||
|
|
||||||
|
if (_uses_gain_mapping) {
|
||||||
|
v = gain_to_slider_position (dB_to_coefficient (v));
|
||||||
|
} else {
|
||||||
|
model_to_view_y (v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AutomationLine::invalid_point (ALPoints& p, uint32_t index)
|
AutomationLine::invalid_point (ALPoints& p, uint32_t index)
|
||||||
{
|
{
|
||||||
|
|
@ -1165,7 +1242,7 @@ AutomationLine::set_state (const XMLNode &node)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AutomationLine::view_to_model_y (double& y)
|
AutomationLine::view_to_model_y (double& y) const
|
||||||
{
|
{
|
||||||
/* TODO: This should be more generic ... */
|
/* TODO: This should be more generic ... */
|
||||||
if (alist->parameter().type() == GainAutomation) {
|
if (alist->parameter().type() == GainAutomation) {
|
||||||
|
|
@ -1183,7 +1260,7 @@ AutomationLine::view_to_model_y (double& y)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AutomationLine::model_to_view_y (double& y)
|
AutomationLine::model_to_view_y (double& y) const
|
||||||
{
|
{
|
||||||
/* TODO: This should be more generic ... */
|
/* TODO: This should be more generic ... */
|
||||||
if (alist->parameter().type() == GainAutomation) {
|
if (alist->parameter().type() == GainAutomation) {
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,6 @@
|
||||||
#include <ardour/automation_list.h>
|
#include <ardour/automation_list.h>
|
||||||
|
|
||||||
|
|
||||||
using std::vector;
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
class AutomationLine;
|
class AutomationLine;
|
||||||
class ControlPoint;
|
class ControlPoint;
|
||||||
class PointSelection;
|
class PointSelection;
|
||||||
|
|
@ -66,8 +63,8 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
||||||
void set_selected_points (PointSelection&);
|
void set_selected_points (PointSelection&);
|
||||||
void get_selectables (nframes_t& start, nframes_t& end,
|
void get_selectables (nframes_t& start, nframes_t& end,
|
||||||
double botfrac, double topfrac,
|
double botfrac, double topfrac,
|
||||||
list<Selectable*>& results);
|
std::list<Selectable*>& results);
|
||||||
void get_inverted_selectables (Selection&, list<Selectable*>& results);
|
void get_inverted_selectables (Selection&, std::list<Selectable*>& results);
|
||||||
|
|
||||||
virtual void remove_point (ControlPoint&);
|
virtual void remove_point (ControlPoint&);
|
||||||
bool control_points_adjacent (double xval, uint32_t& before, uint32_t& after);
|
bool control_points_adjacent (double xval, uint32_t& before, uint32_t& after);
|
||||||
|
|
@ -94,7 +91,8 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
||||||
void show ();
|
void show ();
|
||||||
void hide ();
|
void hide ();
|
||||||
void set_height (guint32);
|
void set_height (guint32);
|
||||||
void set_verbose_cursor_uses_gain_mapping (bool yn);
|
void set_uses_gain_mapping (bool yn);
|
||||||
|
bool get_uses_gain_mapping () const { return _uses_gain_mapping; }
|
||||||
|
|
||||||
TimeAxisView& trackview;
|
TimeAxisView& trackview;
|
||||||
|
|
||||||
|
|
@ -105,9 +103,11 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
||||||
void show_selection();
|
void show_selection();
|
||||||
void hide_selection ();
|
void hide_selection ();
|
||||||
|
|
||||||
virtual string get_verbose_cursor_string (double);
|
string get_verbose_cursor_string (double) const;
|
||||||
virtual void view_to_model_y (double&);
|
string fraction_to_string (double) const;
|
||||||
virtual void model_to_view_y (double&);
|
double string_to_fraction (string const &) const;
|
||||||
|
void view_to_model_y (double&) const;
|
||||||
|
void model_to_view_y (double&) const;
|
||||||
|
|
||||||
void set_list(boost::shared_ptr<ARDOUR::AutomationList> list);
|
void set_list(boost::shared_ptr<ARDOUR::AutomationList> list);
|
||||||
boost::shared_ptr<ARDOUR::AutomationList> the_list() const { return alist; }
|
boost::shared_ptr<ARDOUR::AutomationList> the_list() const { return alist; }
|
||||||
|
|
@ -125,6 +125,8 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
||||||
int set_state (const XMLNode&);
|
int set_state (const XMLNode&);
|
||||||
void set_colors();
|
void set_colors();
|
||||||
|
|
||||||
|
void modify_point_y (ControlPoint&, double);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
string _name;
|
string _name;
|
||||||
|
|
@ -133,7 +135,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
||||||
boost::shared_ptr<ARDOUR::AutomationList> alist;
|
boost::shared_ptr<ARDOUR::AutomationList> alist;
|
||||||
|
|
||||||
bool _visible : 1;
|
bool _visible : 1;
|
||||||
bool _vc_uses_gain_mapping : 1;
|
bool _uses_gain_mapping : 1;
|
||||||
bool terminal_points_can_slide : 1;
|
bool terminal_points_can_slide : 1;
|
||||||
bool update_pending : 1;
|
bool update_pending : 1;
|
||||||
bool no_draw : 1;
|
bool no_draw : 1;
|
||||||
|
|
@ -144,7 +146,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
||||||
ArdourCanvas::Group* group;
|
ArdourCanvas::Group* group;
|
||||||
ArdourCanvas::Line* line; /* line */
|
ArdourCanvas::Line* line; /* line */
|
||||||
ArdourCanvas::Points line_points; /* coordinates for canvas line */
|
ArdourCanvas::Points line_points; /* coordinates for canvas line */
|
||||||
vector<ControlPoint*> control_points; /* visible control points */
|
std::vector<ControlPoint*> control_points; /* visible control points */
|
||||||
|
|
||||||
struct ALPoint {
|
struct ALPoint {
|
||||||
double x;
|
double x;
|
||||||
|
|
|
||||||
|
|
@ -1603,6 +1603,7 @@ public:
|
||||||
void edit_meter_section (ARDOUR::MeterSection*);
|
void edit_meter_section (ARDOUR::MeterSection*);
|
||||||
void edit_tempo_marker (ArdourCanvas::Item*);
|
void edit_tempo_marker (ArdourCanvas::Item*);
|
||||||
void edit_meter_marker (ArdourCanvas::Item*);
|
void edit_meter_marker (ArdourCanvas::Item*);
|
||||||
|
void edit_control_point (ArdourCanvas::Item*);
|
||||||
|
|
||||||
void marker_menu_edit ();
|
void marker_menu_edit ();
|
||||||
void marker_menu_remove ();
|
void marker_menu_remove ();
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "editing.h"
|
#include "editing.h"
|
||||||
#include "rgb_macros.h"
|
#include "rgb_macros.h"
|
||||||
|
#include "control_point_dialog.h"
|
||||||
|
|
||||||
#include <ardour/types.h>
|
#include <ardour/types.h>
|
||||||
#include <ardour/profile.h>
|
#include <ardour/profile.h>
|
||||||
|
|
@ -1071,6 +1072,10 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ControlPointItem:
|
||||||
|
edit_control_point (item);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -3202,6 +3207,28 @@ Editor::control_point_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent
|
||||||
cp->line().end_drag (cp);
|
cp->line().end_drag (cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Editor::edit_control_point (ArdourCanvas::Item* item)
|
||||||
|
{
|
||||||
|
ControlPoint* p = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
|
||||||
|
|
||||||
|
if (p == 0) {
|
||||||
|
fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg;
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlPointDialog d (p);
|
||||||
|
d.set_position (Gtk::WIN_POS_MOUSE);
|
||||||
|
ensure_float (d);
|
||||||
|
|
||||||
|
if (d.run () != RESPONSE_ACCEPT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->line().modify_point_y (*p, d.get_y_fraction ());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Editor::start_line_grab_from_regionview (ArdourCanvas::Item* item, GdkEvent* event)
|
Editor::start_line_grab_from_regionview (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ AudioRegionGainLine::AudioRegionGainLine (const string & name, Session& s, Audio
|
||||||
assert(l->parameter().type() == EnvelopeAutomation);
|
assert(l->parameter().type() == EnvelopeAutomation);
|
||||||
|
|
||||||
group->raise_to_top ();
|
group->raise_to_top ();
|
||||||
set_verbose_cursor_uses_gain_mapping (true);
|
set_uses_gain_mapping (true);
|
||||||
terminal_points_can_slide = false;
|
terminal_points_can_slide = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ class RegionView : public TimeAxisViewItem
|
||||||
|
|
||||||
RegionEditor* editor;
|
RegionEditor* editor;
|
||||||
|
|
||||||
vector<ControlPoint *> control_points;
|
std::vector<ControlPoint *> control_points;
|
||||||
double current_visible_sync_position;
|
double current_visible_sync_position;
|
||||||
|
|
||||||
bool valid; ///< see StreamView::redisplay_diskstream()
|
bool valid; ///< see StreamView::redisplay_diskstream()
|
||||||
|
|
@ -142,7 +142,7 @@ class RegionView : public TimeAxisViewItem
|
||||||
bool wait_for_data;
|
bool wait_for_data;
|
||||||
sigc::connection data_ready_connection;
|
sigc::connection data_ready_connection;
|
||||||
|
|
||||||
vector<GhostRegion*> ghosts;
|
std::vector<GhostRegion*> ghosts;
|
||||||
|
|
||||||
typedef std::map<const Evoral::Parameter, boost::shared_ptr<AutomationRegionView> > AutomationChildren;
|
typedef std::map<const Evoral::Parameter, boost::shared_ptr<AutomationRegionView> > AutomationChildren;
|
||||||
AutomationChildren _automation_children;
|
AutomationChildren _automation_children;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue