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
|
@ -137,6 +137,7 @@ canvas-simpleline.c
|
|||
canvas-simplerect.c
|
||||
canvas-waveview.c
|
||||
control_point.cc
|
||||
control_point_dialog.cc
|
||||
crossfade_edit.cc
|
||||
crossfade_view.cc
|
||||
curvetest.cc
|
||||
|
|
|
@ -64,7 +64,7 @@ AutomationLine::AutomationLine (const string& name, TimeAxisView& tv, ArdourCanv
|
|||
_interpolation = al->interpolation();
|
||||
points_visible = false;
|
||||
update_pending = false;
|
||||
_vc_uses_gain_mapping = false;
|
||||
_uses_gain_mapping = false;
|
||||
no_draw = false;
|
||||
_visible = 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);
|
||||
|
||||
if (alist->parameter().type() == GainAutomation)
|
||||
set_verbose_cursor_uses_gain_mapping (true);
|
||||
if (alist->parameter().type() == GainAutomation) {
|
||||
set_uses_gain_mapping (true);
|
||||
}
|
||||
|
||||
set_interpolation(alist->interpolation());
|
||||
}
|
||||
|
@ -176,10 +177,10 @@ AutomationLine::set_line_color (uint32_t color)
|
|||
}
|
||||
|
||||
void
|
||||
AutomationLine::set_verbose_cursor_uses_gain_mapping (bool yn)
|
||||
AutomationLine::set_uses_gain_mapping (bool yn)
|
||||
{
|
||||
if (yn != _vc_uses_gain_mapping) {
|
||||
_vc_uses_gain_mapping = yn;
|
||||
if (yn != _uses_gain_mapping) {
|
||||
_uses_gain_mapping = yn;
|
||||
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
|
||||
AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool with_push)
|
||||
{
|
||||
|
@ -602,19 +638,35 @@ AutomationLine::determine_visible_control_points (ALPoints& points)
|
|||
}
|
||||
|
||||
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];
|
||||
|
||||
if (_vc_uses_gain_mapping) {
|
||||
if (_uses_gain_mapping) {
|
||||
if (fraction == 0.0) {
|
||||
snprintf (buf, sizeof (buf), "-inf dB");
|
||||
snprintf (buf, sizeof (buf), "-inf");
|
||||
} 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 {
|
||||
view_to_model_y(fraction);
|
||||
if (EventTypeMap::instance().is_integer(alist->parameter())) {
|
||||
view_to_model_y (fraction);
|
||||
if (EventTypeMap::instance().is_integer (alist->parameter())) {
|
||||
snprintf (buf, sizeof (buf), "%d", (int)fraction);
|
||||
} else {
|
||||
snprintf (buf, sizeof (buf), "%.2f", fraction);
|
||||
|
@ -624,6 +676,31 @@ AutomationLine::get_verbose_cursor_string (double fraction)
|
|||
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
|
||||
AutomationLine::invalid_point (ALPoints& p, uint32_t index)
|
||||
{
|
||||
|
@ -1165,7 +1242,7 @@ AutomationLine::set_state (const XMLNode &node)
|
|||
}
|
||||
|
||||
void
|
||||
AutomationLine::view_to_model_y (double& y)
|
||||
AutomationLine::view_to_model_y (double& y) const
|
||||
{
|
||||
/* TODO: This should be more generic ... */
|
||||
if (alist->parameter().type() == GainAutomation) {
|
||||
|
@ -1183,7 +1260,7 @@ AutomationLine::view_to_model_y (double& y)
|
|||
}
|
||||
|
||||
void
|
||||
AutomationLine::model_to_view_y (double& y)
|
||||
AutomationLine::model_to_view_y (double& y) const
|
||||
{
|
||||
/* TODO: This should be more generic ... */
|
||||
if (alist->parameter().type() == GainAutomation) {
|
||||
|
|
|
@ -36,9 +36,6 @@
|
|||
#include <ardour/automation_list.h>
|
||||
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
class AutomationLine;
|
||||
class ControlPoint;
|
||||
class PointSelection;
|
||||
|
@ -66,8 +63,8 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
|||
void set_selected_points (PointSelection&);
|
||||
void get_selectables (nframes_t& start, nframes_t& end,
|
||||
double botfrac, double topfrac,
|
||||
list<Selectable*>& results);
|
||||
void get_inverted_selectables (Selection&, list<Selectable*>& results);
|
||||
std::list<Selectable*>& results);
|
||||
void get_inverted_selectables (Selection&, std::list<Selectable*>& results);
|
||||
|
||||
virtual void remove_point (ControlPoint&);
|
||||
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 hide ();
|
||||
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;
|
||||
|
||||
|
@ -105,9 +103,11 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
|||
void show_selection();
|
||||
void hide_selection ();
|
||||
|
||||
virtual string get_verbose_cursor_string (double);
|
||||
virtual void view_to_model_y (double&);
|
||||
virtual void model_to_view_y (double&);
|
||||
string get_verbose_cursor_string (double) const;
|
||||
string fraction_to_string (double) const;
|
||||
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);
|
||||
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&);
|
||||
void set_colors();
|
||||
|
||||
void modify_point_y (ControlPoint&, double);
|
||||
|
||||
protected:
|
||||
|
||||
string _name;
|
||||
|
@ -133,7 +135,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
|||
boost::shared_ptr<ARDOUR::AutomationList> alist;
|
||||
|
||||
bool _visible : 1;
|
||||
bool _vc_uses_gain_mapping : 1;
|
||||
bool _uses_gain_mapping : 1;
|
||||
bool terminal_points_can_slide : 1;
|
||||
bool update_pending : 1;
|
||||
bool no_draw : 1;
|
||||
|
@ -144,7 +146,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
|||
ArdourCanvas::Group* group;
|
||||
ArdourCanvas::Line* line; /* 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 {
|
||||
double x;
|
||||
|
@ -180,7 +182,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
|||
|
||||
ARDOUR::AutomationList::InterpolationStyle _interpolation;
|
||||
|
||||
void modify_view_point(ControlPoint&, double, double, bool with_push);
|
||||
void modify_view_point (ControlPoint&, double, double, bool with_push);
|
||||
void reset_line_coords (ControlPoint&);
|
||||
|
||||
double control_point_box_size ();
|
||||
|
|
|
@ -1603,6 +1603,7 @@ public:
|
|||
void edit_meter_section (ARDOUR::MeterSection*);
|
||||
void edit_tempo_marker (ArdourCanvas::Item*);
|
||||
void edit_meter_marker (ArdourCanvas::Item*);
|
||||
void edit_control_point (ArdourCanvas::Item*);
|
||||
|
||||
void marker_menu_edit ();
|
||||
void marker_menu_remove ();
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "keyboard.h"
|
||||
#include "editing.h"
|
||||
#include "rgb_macros.h"
|
||||
#include "control_point_dialog.h"
|
||||
|
||||
#include <ardour/types.h>
|
||||
#include <ardour/profile.h>
|
||||
|
@ -1071,6 +1072,10 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
|||
}
|
||||
break;
|
||||
|
||||
case ControlPointItem:
|
||||
edit_control_point (item);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -3202,6 +3207,28 @@ Editor::control_point_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent
|
|||
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
|
||||
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);
|
||||
|
||||
group->raise_to_top ();
|
||||
set_verbose_cursor_uses_gain_mapping (true);
|
||||
set_uses_gain_mapping (true);
|
||||
terminal_points_can_slide = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ class RegionView : public TimeAxisViewItem
|
|||
|
||||
RegionEditor* editor;
|
||||
|
||||
vector<ControlPoint *> control_points;
|
||||
std::vector<ControlPoint *> control_points;
|
||||
double current_visible_sync_position;
|
||||
|
||||
bool valid; ///< see StreamView::redisplay_diskstream()
|
||||
|
@ -142,7 +142,7 @@ class RegionView : public TimeAxisViewItem
|
|||
bool wait_for_data;
|
||||
sigc::connection data_ready_connection;
|
||||
|
||||
vector<GhostRegion*> ghosts;
|
||||
std::vector<GhostRegion*> ghosts;
|
||||
|
||||
typedef std::map<const Evoral::Parameter, boost::shared_ptr<AutomationRegionView> > AutomationChildren;
|
||||
AutomationChildren _automation_children;
|
||||
|
|
Loading…
Reference in New Issue