summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2012-04-22 14:03:07 +0000
committerCarl Hetherington <carl@carlh.net>2012-04-22 14:03:07 +0000
commita4434809e147d7f091fd488d047c531ff4c344c9 (patch)
tree2ffc14ef55a0ca310b4f772bcb87d662084a752c
parent82c867bf2a6f4de102707b812a87d68e3bd6e170 (diff)
Use a list of ControlPoints to hold the automation selection,
rather than a time range. This makes more sense now that we display every point on an automation line, rather than just a subset. Makes the code a fair bit simpler, and should fix some unexpected behaviours, especially when cutting automation points. git-svn-id: svn://localhost/ardour2/branches/3.0@12054 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/automation_line.cc49
-rw-r--r--gtk2_ardour/automation_line.h5
-rw-r--r--gtk2_ardour/automation_time_axis.cc184
-rw-r--r--gtk2_ardour/automation_time_axis.h6
-rw-r--r--gtk2_ardour/control_point.cc4
-rw-r--r--gtk2_ardour/control_point.h2
-rw-r--r--gtk2_ardour/editor_ops.cc90
-rw-r--r--gtk2_ardour/point_selection.h5
-rw-r--r--gtk2_ardour/selection.cc116
-rw-r--r--gtk2_ardour/selection.h4
-rw-r--r--gtk2_ardour/time_info_box.cc7
-rw-r--r--libs/evoral/evoral/ControlList.hpp1
-rw-r--r--libs/evoral/src/ControlList.cpp31
13 files changed, 139 insertions, 365 deletions
diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc
index 2f91c113bd..2af484b409 100644
--- a/gtk2_ardour/automation_line.cc
+++ b/gtk2_ardour/automation_line.cc
@@ -731,38 +731,6 @@ AutomationLine::get_inverted_selectables (Selection&, list<Selectable*>& /*resul
// hmmm ....
}
-/** Take a PointSelection and find ControlPoints that fall within it */
-list<ControlPoint*>
-AutomationLine::point_selection_to_control_points (PointSelection const & s)
-{
- list<ControlPoint*> cp;
-
- for (PointSelection::const_iterator i = s.begin(); i != s.end(); ++i) {
-
- if (i->track != &trackview) {
- continue;
- }
-
- double const bot = (1 - i->high_fract) * trackview.current_height ();
- double const top = (1 - i->low_fract) * trackview.current_height ();
-
- for (vector<ControlPoint*>::iterator j = control_points.begin(); j != control_points.end(); ++j) {
-
- double const rstart = trackview.editor().frame_to_unit (_time_converter->to (i->start) - _offset);
- double const rend = trackview.editor().frame_to_unit (_time_converter->to (i->end) - _offset);
-
- if ((*j)->get_x() >= rstart && (*j)->get_x() <= rend) {
- if ((*j)->get_y() >= bot && (*j)->get_y() <= top) {
- cp.push_back (*j);
- }
- }
- }
-
- }
-
- return cp;
-}
-
void
AutomationLine::set_selected_points (PointSelection const & points)
{
@@ -770,11 +738,8 @@ AutomationLine::set_selected_points (PointSelection const & points)
(*i)->set_selected (false);
}
- if (!points.empty()) {
- list<ControlPoint*> cp = point_selection_to_control_points (points);
- for (list<ControlPoint*>::iterator i = cp.begin(); i != cp.end(); ++i) {
- (*i)->set_selected (true);
- }
+ for (PointSelection::const_iterator i = points.begin(); i != points.end(); ++i) {
+ (*i)->set_selected (true);
}
set_colors ();
@@ -1147,13 +1112,19 @@ AutomationLine::get_point_x_range () const
pair<framepos_t, framepos_t> r (max_framepos, 0);
for (AutomationList::const_iterator i = the_list()->begin(); i != the_list()->end(); ++i) {
- r.first = min (r.first, _time_converter->to ((*i)->when) + _offset + _time_converter->origin_b ());
- r.second = max (r.second, _time_converter->to ((*i)->when) + _offset + _time_converter->origin_b ());
+ r.first = min (r.first, session_position (i));
+ r.second = max (r.second, session_position (i));
}
return r;
}
+framepos_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)
{
diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h
index 841d7e6f55..82debde51b 100644
--- a/gtk2_ardour/automation_line.h
+++ b/gtk2_ardour/automation_line.h
@@ -66,7 +66,6 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible
void reset ();
void clear ();
- std::list<ControlPoint*> point_selection_to_control_points (PointSelection const &);
void set_selected_points (PointSelection const &);
void get_selectables (ARDOUR::framepos_t, ARDOUR::framepos_t, double, double, std::list<Selectable*>&);
void get_inverted_selectables (Selection&, std::list<Selectable*>& results);
@@ -145,6 +144,8 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible
void set_offset (ARDOUR::framecnt_t);
void set_width (ARDOUR::framecnt_t);
+ framepos_t session_position (ARDOUR::AutomationList::const_iterator) const;
+
protected:
std::string _name;
@@ -153,7 +154,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible
boost::shared_ptr<ARDOUR::AutomationList> alist;
Evoral::TimeConverter<double, ARDOUR::framepos_t>* _time_converter;
- /** true if _time_converter belongs to us (ie we should delete it) */
+ /** true if _time_converter belongs to us (ie we should delete it on destruction) */
bool _our_time_converter;
bool _visible : 1;
diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc
index 586e2aef18..738e835cce 100644
--- a/gtk2_ardour/automation_time_axis.cc
+++ b/gtk2_ardour/automation_time_axis.cc
@@ -44,6 +44,7 @@
#include "rgb_macros.h"
#include "point_selection.h"
#include "canvas_impl.h"
+#include "control_point.h"
#include "utils.h"
#include "i18n.h"
@@ -592,172 +593,6 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when,
_session->set_dirty ();
}
-void
-AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
-{
- list<boost::shared_ptr<AutomationLine> > lines;
- if (_line) {
- lines.push_back (_line);
- } else if (_view) {
- lines = _view->get_lines ();
- }
-
- for (list<boost::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
- cut_copy_clear_one (**i, selection, op);
- }
-}
-
-void
-AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
-{
- boost::shared_ptr<Evoral::ControlList> what_we_got;
- boost::shared_ptr<AutomationList> alist (line.the_list());
-
- XMLNode &before = alist->get_state();
-
- /* convert time selection to automation list model coordinates */
- const Evoral::TimeConverter<double, ARDOUR::framepos_t>& tc = line.time_converter ();
- double const start = tc.from (selection.time.front().start - tc.origin_b ());
- double const end = tc.from (selection.time.front().end - tc.origin_b ());
-
- switch (op) {
- case Delete:
- if (alist->cut (start, end) != 0) {
- _session->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
- }
- break;
-
- case Cut:
-
- if ((what_we_got = alist->cut (start, end)) != 0) {
- _editor.get_cut_buffer().add (what_we_got);
- _session->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
- }
- break;
- case Copy:
- if ((what_we_got = alist->copy (start, end)) != 0) {
- _editor.get_cut_buffer().add (what_we_got);
- }
- break;
-
- case Clear:
- if ((what_we_got = alist->cut (start, end)) != 0) {
- _session->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
- }
- break;
- }
-
- if (what_we_got) {
- for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
- double when = (*x)->when;
- double val = (*x)->value;
- line.model_to_view_coord (when, val);
- (*x)->when = when;
- (*x)->value = val;
- }
- }
-}
-
-void
-AutomationTimeAxisView::reset_objects (PointSelection& selection)
-{
- list<boost::shared_ptr<AutomationLine> > lines;
- if (_line) {
- lines.push_back (_line);
- } else if (_view) {
- lines = _view->get_lines ();
- }
-
- for (list<boost::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
- reset_objects_one (**i, selection);
- }
-}
-
-void
-AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
-{
- boost::shared_ptr<AutomationList> alist(line.the_list());
-
- _session->add_command (new MementoCommand<AutomationList>(*alist.get(), &alist->get_state(), 0));
-
- for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
-
- if ((*i).track != this) {
- continue;
- }
-
- alist->reset_range ((*i).start, (*i).end);
- }
-}
-
-void
-AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
-{
- list<boost::shared_ptr<AutomationLine> > lines;
- if (_line) {
- lines.push_back (_line);
- } else if (_view) {
- lines = _view->get_lines ();
- }
-
- for (list<boost::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
- cut_copy_clear_objects_one (**i, selection, op);
- }
-}
-
-void
-AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
-{
- boost::shared_ptr<Evoral::ControlList> what_we_got;
- boost::shared_ptr<AutomationList> alist(line.the_list());
-
- XMLNode &before = alist->get_state();
-
- for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
-
- if ((*i).track != this) {
- continue;
- }
-
- switch (op) {
- case Delete:
- if (alist->cut ((*i).start, (*i).end) != 0) {
- _session->add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
- }
- break;
- case Cut:
- if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
- _editor.get_cut_buffer().add (what_we_got);
- _session->add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
- }
- break;
- case Copy:
- if ((what_we_got = alist->copy ((*i).start, (*i).end)) != 0) {
- _editor.get_cut_buffer().add (what_we_got);
- }
- break;
-
- case Clear:
- if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
- _session->add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
- }
- break;
- }
- }
-
- delete &before;
-
- if (what_we_got) {
- for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
- double when = (*x)->when;
- double val = (*x)->value;
- line.model_to_view_coord (when, val);
- (*x)->when = when;
- (*x)->value = val;
- }
- }
-}
-
/** Paste a selection.
* @param pos Position to paste to (session frames).
* @param times Number of times to paste.
@@ -794,25 +629,10 @@ AutomationTimeAxisView::paste_one (AutomationLine& line, framepos_t pos, float t
return false;
}
- /* Make a copy of the list because we have to scale the
- values from view coordinates to model coordinates, and we're
- not supposed to modify the points in the selection.
- */
-
- AutomationList copy (**p);
-
- for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
- double when = (*x)->when;
- double val = (*x)->value;
- line.view_to_model_coord (when, val);
- (*x)->when = when;
- (*x)->value = val;
- }
-
double const model_pos = line.time_converter().from (pos - line.time_converter().origin_b ());
XMLNode &before = alist->get_state();
- alist->paste (copy, model_pos, times);
+ alist->paste (**p, model_pos, times);
_session->add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
return true;
diff --git a/gtk2_ardour/automation_time_axis.h b/gtk2_ardour/automation_time_axis.h
index 7706ed7ee3..913cd1b467 100644
--- a/gtk2_ardour/automation_time_axis.h
+++ b/gtk2_ardour/automation_time_axis.h
@@ -91,10 +91,7 @@ class AutomationTimeAxisView : public TimeAxisView {
/* editing operations */
- void cut_copy_clear (Selection&, Editing::CutCopyOp);
- void cut_copy_clear_objects (PointSelection&, Editing::CutCopyOp);
bool paste (ARDOUR::framepos_t, float times, Selection&, size_t nth);
- void reset_objects (PointSelection&);
int set_state (const XMLNode&, int version);
@@ -169,10 +166,7 @@ class AutomationTimeAxisView : public TimeAxisView {
void build_display_menu ();
- void cut_copy_clear_one (AutomationLine&, Selection&, Editing::CutCopyOp);
- void cut_copy_clear_objects_one (AutomationLine&, PointSelection&, Editing::CutCopyOp);
bool paste_one (AutomationLine&, ARDOUR::framepos_t, float times, Selection&, size_t nth);
- void reset_objects_one (AutomationLine&, PointSelection&);
void route_going_away ();
void set_automation_state (ARDOUR::AutoState);
diff --git a/gtk2_ardour/control_point.cc b/gtk2_ardour/control_point.cc
index bc7301dc1c..d869e094aa 100644
--- a/gtk2_ardour/control_point.cc
+++ b/gtk2_ardour/control_point.cc
@@ -30,6 +30,8 @@ using namespace ARDOUR;
using namespace PBD;
using namespace Gnome; // for Canvas
+PBD::Signal1<void, ControlPoint *> ControlPoint::CatchDeletion;
+
ControlPoint::ControlPoint (AutomationLine& al)
: _line (al)
{
@@ -82,6 +84,8 @@ ControlPoint::ControlPoint (const ControlPoint& other, bool /*dummy_arg_to_force
ControlPoint::~ControlPoint ()
{
+ CatchDeletion (this); /* EMIT SIGNAL */
+
delete _item;
}
diff --git a/gtk2_ardour/control_point.h b/gtk2_ardour/control_point.h
index 603d062ec4..0c2bf1e01d 100644
--- a/gtk2_ardour/control_point.h
+++ b/gtk2_ardour/control_point.h
@@ -83,6 +83,8 @@ class ControlPoint : public Selectable
ARDOUR::AutomationList::iterator model() const { return _model; }
AutomationLine& line() const { return _line; }
+ static PBD::Signal1<void, ControlPoint *> CatchDeletion;
+
private:
ArdourCanvas::SimpleRect* _item;
AutomationLine& _line;
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 6b48311b15..bae511e031 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -63,6 +63,7 @@
#include "route_time_axis.h"
#include "audio_time_axis.h"
#include "automation_time_axis.h"
+#include "control_point.h"
#include "streamview.h"
#include "audio_streamview.h"
#include "audio_region_view.h"
@@ -3721,19 +3722,87 @@ Editor::cut_copy (CutCopyOp op)
}
}
+struct AutomationRecord {
+ AutomationRecord () : state (0) {}
+ AutomationRecord (XMLNode* s) : state (s) {}
+
+ XMLNode* state; ///< state before any operation
+ boost::shared_ptr<Evoral::ControlList> copy; ///< copied events for the cut buffer
+};
+
/** Cut, copy or clear selected automation points.
- * @param op Operation (Cut, Copy or Clear)
+ * @param op Operation (Cut, Copy or Clear)
*/
void
Editor::cut_copy_points (CutCopyOp op)
{
+ if (selection->points.empty ()) {
+ return;
+ }
+
+ /* XXX: not ideal, as there may be more than one track involved in the point selection */
+ _last_cut_copy_source_track = &selection->points.front()->line().trackview;
+
+ /* Keep a record of the AutomationLists that we end up using in this operation */
+ typedef std::map<boost::shared_ptr<AutomationList>, AutomationRecord> Lists;
+ Lists lists;
+
+ /* Go through all selected points, making an AutomationRecord for each distinct AutomationList */
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
+ boost::shared_ptr<AutomationList> al = (*i)->line().the_list();
+ if (lists.find (al) == lists.end ()) {
+ /* We haven't seen this list yet, so make a record for it. This includes
+ taking a copy of its current state, in case this is needed for undo later.
+ */
+ lists[al] = AutomationRecord (&al->get_state ());
+ }
+ }
+
+ if (op == Cut || op == Copy) {
+ /* This operation will involve putting things in the cut buffer, so create an empty
+ ControlList for each of our source lists to put the cut buffer data in.
+ */
+ for (Lists::iterator i = lists.begin(); i != lists.end(); ++i) {
+ i->second.copy = i->first->create (i->first->parameter ());
+ }
- AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>((*i).track);
- _last_cut_copy_source_track = atv;
+ /* Add all selected points to the relevant copy ControlLists */
+ for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
+ boost::shared_ptr<AutomationList> al = (*i)->line().the_list();
+ AutomationList::const_iterator j = (*i)->model ();
+ lists[al].copy->add ((*j)->when, (*j)->value);
+ }
+
+ for (Lists::iterator i = lists.begin(); i != lists.end(); ++i) {
+ /* Correct this copy list so that it starts at time 0 */
+ double const start = i->second.copy->front()->when;
+ for (AutomationList::iterator j = i->second.copy->begin(); j != i->second.copy->end(); ++j) {
+ (*j)->when -= start;
+ }
- if (atv) {
- atv->cut_copy_clear_objects (selection->points, op);
+ /* And add it to the cut buffer */
+ cut_buffer->add (i->second.copy);
+ }
+ }
+
+ if (op == Delete || op == Cut) {
+ /* This operation needs to remove things from the main AutomationList, so do that now */
+
+ for (Lists::iterator i = lists.begin(); i != lists.end(); ++i) {
+ i->first->freeze ();
+ }
+
+ /* Remove each selected point from its AutomationList */
+ for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
+ boost::shared_ptr<AutomationList> al = (*i)->line().the_list();
+ al->erase ((*i)->model ());
+ }
+
+ /* Thaw the lists and add undo records for them */
+ for (Lists::iterator i = lists.begin(); i != lists.end(); ++i) {
+ boost::shared_ptr<AutomationList> al = i->first;
+ al->thaw ();
+ _session->add_command (new MementoCommand<AutomationList> (*al.get(), i->second.state, &(al->get_state ())));
}
}
}
@@ -4229,18 +4298,13 @@ Editor::duplicate_selection (float times)
commit_reversible_command ();
}
+/** Reset all selected points to the relevant default value */
void
Editor::reset_point_selection ()
{
- /* reset all selected points to the relevant default value */
-
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
-
- AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>((*i).track);
-
- if (atv) {
- atv->reset_objects (selection->points);
- }
+ ARDOUR::AutomationList::iterator j = (*i)->model ();
+ (*j)->value = (*i)->line().the_list()->default_value ();
}
}
diff --git a/gtk2_ardour/point_selection.h b/gtk2_ardour/point_selection.h
index 85acc90ec8..5ed5ae1573 100644
--- a/gtk2_ardour/point_selection.h
+++ b/gtk2_ardour/point_selection.h
@@ -21,11 +21,10 @@
#define __ardour_gtk_point_selection_h__
#include <list>
-#include <boost/noncopyable.hpp>
-#include "automation_range.h"
+class ControlPoint;
-struct PointSelection : public std::list<AutomationRange>
+struct PointSelection : public std::list<ControlPoint *>
{
};
diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc
index 4d9262bb3a..afc13f1b41 100644
--- a/gtk2_ardour/selection.cc
+++ b/gtk2_ardour/selection.cc
@@ -62,6 +62,9 @@ Selection::Selection (const PublicEditor* e)
void (Selection::*marker_remove)(Marker*) = &Selection::remove;
Marker::CatchDeletion.connect (*this, MISSING_INVALIDATOR, ui_bind (marker_remove, this, _1), gui_context());
+
+ void (Selection::*point_remove)(ControlPoint*) = &Selection::remove;
+ ControlPoint::CatchDeletion.connect (*this, MISSING_INVALIDATOR, ui_bind (point_remove, this, _1), gui_context());
}
#if 0
@@ -516,7 +519,6 @@ Selection::add (boost::shared_ptr<Evoral::ControlList> cl)
if (!al) {
warning << "Programming error: Selected list is not an ARDOUR::AutomationList" << endmsg;
return;
- return;
}
if (find (lines.begin(), lines.end(), al) == lines.end()) {
lines.push_back (al);
@@ -537,6 +539,15 @@ Selection::remove (TimeAxisView* track)
}
void
+Selection::remove (ControlPoint* p)
+{
+ PointSelection::iterator i = find (points.begin(), points.end(), p);
+ if (i != points.end ()) {
+ points.erase (i);
+ }
+}
+
+void
Selection::remove (const TrackViewList& track_list)
{
bool changed = false;
@@ -879,17 +890,22 @@ void
Selection::toggle (ControlPoint* cp)
{
cp->set_selected (!cp->get_selected ());
- set_point_selection_from_line (cp->line ());
+ PointSelection::iterator i = find (points.begin(), points.end(), cp);
+ if (i == points.end()) {
+ points.push_back (cp);
+ } else {
+ points.erase (i);
+ }
+
+ PointsChanged (); /* EMIT SIGNAL */
}
void
Selection::toggle (vector<ControlPoint*> const & cps)
{
for (vector<ControlPoint*>::const_iterator i = cps.begin(); i != cps.end(); ++i) {
- (*i)->set_selected (!(*i)->get_selected ());
+ toggle (*i);
}
-
- set_point_selection_from_line (cps.front()->line ());
}
void
@@ -935,6 +951,13 @@ Selection::set (list<Selectable*> const & selectables)
add (selectables);
}
+void
+Selection::add (PointSelection const & s)
+{
+ for (PointSelection::const_iterator i = s.begin(); i != s.end(); ++i) {
+ points.push_back (*i);
+ }
+}
void
Selection::add (list<Selectable*> const & selectables)
@@ -979,17 +1002,16 @@ void
Selection::add (ControlPoint* cp)
{
cp->set_selected (true);
- set_point_selection_from_line (cp->line ());
+ points.push_back (cp);
+ PointsChanged (); /* EMIT SIGNAL */
}
void
Selection::add (vector<ControlPoint*> const & cps)
{
for (vector<ControlPoint*>::const_iterator i = cps.begin(); i != cps.end(); ++i) {
- (*i)->set_selected (true);
+ add (*i);
}
-
- set_point_selection_from_line (cps.front()->line ());
}
void
@@ -999,18 +1021,11 @@ Selection::set (ControlPoint* cp)
return;
}
- /* We're going to set up the PointSelection from the selected ControlPoints
- on this point's line, so we need to deselect all ControlPoints before
- we re-add this one.
- */
-
for (uint32_t i = 0; i < cp->line().npoints(); ++i) {
cp->line().nth (i)->set_selected (false);
}
- vector<ControlPoint*> cps;
- cps.push_back (cp);
- add (cps);
+ add (cp);
}
void
@@ -1083,73 +1098,6 @@ MarkerSelection::range (framepos_t& s, framepos_t& e)
e = std::max (s, e);
}
-/** Automation control point selection is mostly manipulated using the selected state
- * of the ControlPoints themselves. For example, to add a point to a selection, its
- * ControlPoint is marked as selected and then this method is called. It sets up
- * our PointSelection from the selected ControlPoints of a given AutomationLine.
- *
- * We can't use ControlPoints directly in the selection, as we need to express a
- * selection of not just a visible ControlPoint but also (possibly) some invisible
- * points nearby. Hence the selection stores AutomationRanges, and these are synced
- * with ControlPoint selection state using AutomationLine::set_selected_points.
- */
-
-void
-Selection::set_point_selection_from_line (AutomationLine const & line)
-{
- points.clear ();
-
- AutomationRange current (DBL_MAX, 0, 1, 0, &line.trackview);
-
- for (uint32_t i = 0; i < line.npoints(); ++i) {
- ControlPoint const * cp = line.nth (i);
-
- if (cp->get_selected()) {
- /* x and y position of this control point in coordinates suitable for
- an AutomationRange (ie model time and fraction of track height)
- */
- double const x = (*(cp->model()))->when;
- double const y = 1 - (cp->get_y() / line.trackview.current_height ());
-
- /* work out the position of a rectangle the size of a control point centred
- on this point
- */
-
- double const size = cp->size ();
- double const x_size = line.time_converter().from (line.trackview.editor().pixel_to_frame (size));
- double const y_size = size / line.trackview.current_height ();
-
- double const x1 = max (0.0, x - x_size / 2);
- double const x2 = x + x_size / 2;
- double const y1 = max (0.0, y - y_size / 2);
- double const y2 = y + y_size / 2;
-
- /* extend the current AutomationRange to put this point in */
- current.start = min (current.start, x1);
- current.end = max (current.end, x2);
- current.low_fract = min (current.low_fract, y1);
- current.high_fract = max (current.high_fract, y2);
-
- } else {
- /* this point isn't selected; if the current AutomationRange has some
- stuff in it, push it onto the list and make a new one
- */
- if (current.start < DBL_MAX) {
- points.push_back (current);
- current = AutomationRange (DBL_MAX, 0, 1, 0, &line.trackview);
- }
- }
- }
-
- /* Maybe push the current AutomationRange, as above */
- if (current.start < DBL_MAX) {
- points.push_back (current);
- current = AutomationRange (DBL_MAX, 0, 1, 0, &line.trackview);
- }
-
- PointsChanged (); /* EMIT SIGNAL */
-}
-
XMLNode&
Selection::get_state () const
{
diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h
index c474faa5b2..df7212593f 100644
--- a/gtk2_ardour/selection.h
+++ b/gtk2_ardour/selection.h
@@ -165,6 +165,7 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList
void add (Marker*);
void add (const std::list<Marker*>&);
void add (const RegionSelection&);
+ void add (const PointSelection&);
void remove (TimeAxisView*);
void remove (const TrackViewList&);
void remove (const MidiNoteSelection&);
@@ -178,6 +179,7 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList
void remove (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
void remove (const std::list<Selectable*>&);
void remove (Marker*);
+ void remove (ControlPoint *);
void remove_regions (TimeAxisView *);
@@ -202,8 +204,6 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList
int set_state (XMLNode const &, int);
private:
- void set_point_selection_from_line (AutomationLine const &);
-
PublicEditor const * editor;
uint32_t next_time_id;
bool _no_tracks_changed;
diff --git a/gtk2_ardour/time_info_box.cc b/gtk2_ardour/time_info_box.cc
index 00b760952c..12cc8d7571 100644
--- a/gtk2_ardour/time_info_box.cc
+++ b/gtk2_ardour/time_info_box.cc
@@ -32,6 +32,8 @@
#include "time_info_box.h"
#include "audio_clock.h"
#include "editor.h"
+#include "control_point.h"
+#include "automation_line.h"
#include "i18n.h"
@@ -267,8 +269,9 @@ TimeInfoBox::selection_changed ()
s = max_framepos;
e = 0;
for (PointSelection::iterator i = selection.points.begin(); i != selection.points.end(); ++i) {
- s = min (s, (framepos_t) i->start);
- e = max (e, (framepos_t) i->end);
+ framepos_t const p = (*i)->line().session_position ((*i)->model ());
+ s = min (s, p);
+ e = max (e, p);
}
selection_start->set_off (false);
selection_end->set_off (false);
diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp
index 324d03cc28..30b9fca430 100644
--- a/libs/evoral/evoral/ControlList.hpp
+++ b/libs/evoral/evoral/ControlList.hpp
@@ -123,7 +123,6 @@ public:
void fast_simple_add (double when, double value);
void merge_nascent (double when);
- void reset_range (double start, double end);
void erase_range (double start, double end);
void erase (iterator);
void erase (iterator, iterator);
diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp
index e90b28c147..9c38f67b29 100644
--- a/libs/evoral/src/ControlList.cpp
+++ b/libs/evoral/src/ControlList.cpp
@@ -558,37 +558,6 @@ ControlList::erase (double when, double value)
}
void
-ControlList::reset_range (double start, double endt)
-{
- bool reset = false;
-
- {
- Glib::Mutex::Lock lm (_lock);
- ControlEvent cp (start, 0.0f);
- iterator s;
- iterator e;
-
- if ((s = lower_bound (_events.begin(), _events.end(), &cp, time_comparator)) != _events.end()) {
-
- cp.when = endt;
- e = upper_bound (_events.begin(), _events.end(), &cp, time_comparator);
-
- for (iterator i = s; i != e; ++i) {
- (*i)->value = _default_value;
- }
-
- reset = true;
-
- mark_dirty ();
- }
- }
-
- if (reset) {
- maybe_signal_changed ();
- }
-}
-
-void
ControlList::erase_range (double start, double endt)
{
bool erased = false;