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:
Carl Hetherington 2008-12-18 17:46:28 +00:00
parent 058e7f2c01
commit 883eeb8cf2
7 changed files with 137 additions and 29 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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 ();

View File

@ -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 ();

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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;