2 Copyright (C) 2000-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <gtkmm2ext/barcontroller.h>
22 #include "pbd/memento_command.h"
23 #include "ardour/automation_control.h"
24 #include "ardour/event_type_map.h"
25 #include "ardour/route.h"
26 #include "ardour/session.h"
28 #include "ardour_ui.h"
29 #include "automation_time_axis.h"
30 #include "automation_streamview.h"
31 #include "gui_thread.h"
32 #include "route_time_axis.h"
33 #include "automation_line.h"
34 #include "public_editor.h"
35 #include "simplerect.h"
36 #include "selection.h"
37 #include "rgb_macros.h"
38 #include "point_selection.h"
39 #include "canvas_impl.h"
45 using namespace ARDOUR;
48 using namespace Gtkmm2ext;
49 using namespace Editing;
51 Pango::FontDescription* AutomationTimeAxisView::name_font = 0;
52 bool AutomationTimeAxisView::have_name_font = false;
53 const string AutomationTimeAxisView::state_node_name = "AutomationChild";
56 /** \a a the automatable object this time axis is to display data for.
57 * For route/track automation (e.g. gain) pass the route for both \r and \a.
58 * For route child (e.g. plugin) automation, pass the child for \a.
59 * For region automation (e.g. MIDI CC), pass null for \a.
61 AutomationTimeAxisView::AutomationTimeAxisView (Session* s, boost::shared_ptr<Route> r,
62 boost::shared_ptr<Automatable> a, boost::shared_ptr<AutomationControl> c,
63 PublicEditor& e, TimeAxisView& parent, bool show_regions,
64 ArdourCanvas::Canvas& canvas, const string & nom, const string & nomparent)
66 TimeAxisView (s, e, &parent, canvas),
70 _controller(AutomationController::create(a, c->parameter(), c)),
72 _view (show_regions ? new AutomationStreamView(*this) : NULL),
74 auto_button (X_("")) /* force addition of a label */
76 if (!have_name_font) {
77 name_font = get_font_for_style (X_("AutomationTrackName"));
78 have_name_font = true;
86 mode_discrete_item = 0;
89 ignore_state_request = false;
90 first_call_to_set_height = true;
92 _base_rect = new SimpleRect(*_canvas_display);
93 _base_rect->property_x1() = 0.0;
94 _base_rect->property_y1() = 0.0;
95 _base_rect->property_x2() = LONG_MAX - 2;
96 _base_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackOutline.get();
98 /* outline ends and bottom */
99 _base_rect->property_outline_what() = (guint32) (0x1|0x2|0x8);
100 _base_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackFill.get();
102 _base_rect->set_data ("trackview", this);
104 _base_rect->signal_event().connect (sigc::bind (
105 sigc::mem_fun (_editor, &PublicEditor::canvas_automation_track_event),
109 _base_rect->lower_to_bottom();
112 hide_button.add (*(manage (new Gtk::Image (::get_icon("hide")))));
114 auto_button.set_name ("TrackVisualButton");
115 hide_button.set_name ("TrackRemoveButton");
117 auto_button.unset_flags (Gtk::CAN_FOCUS);
118 hide_button.unset_flags (Gtk::CAN_FOCUS);
120 controls_table.set_no_show_all();
122 ARDOUR_UI::instance()->set_tip(auto_button, _("automation state"));
123 ARDOUR_UI::instance()->set_tip(hide_button, _("hide track"));
125 /* rearrange the name display */
127 /* we never show these for automation tracks, so make
128 life easier and remove them.
133 /* move the name label over a bit */
135 string shortpname = _name;
136 bool shortened = false;
139 shortpname = fit_to_pixels (_name, 60, *name_font, ignore_width, true);
141 if (shortpname != _name ){
145 name_label.set_text (shortpname);
146 name_label.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
148 if (nomparent.length()) {
150 /* limit the plug name string */
152 string pname = fit_to_pixels (nomparent, 60, *name_font, ignore_width, true);
153 if (pname != nomparent) {
157 plugname = new Label (pname);
158 plugname->set_name (X_("TrackPlugName"));
160 name_label.set_name (X_("TrackParameterName"));
161 controls_table.remove (name_hbox);
162 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
163 plugname_packed = true;
164 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
167 plugname_packed = false;
171 string tipname = nomparent;
172 if (!tipname.empty()) {
176 ARDOUR_UI::instance()->set_tip(controls_ebox, tipname);
179 /* add the buttons */
180 controls_table.attach (hide_button, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
182 controls_table.attach (auto_button, 5, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
184 /* add bar controller */
185 controls_table.attach (*_controller.get(), 0, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
187 controls_table.show_all ();
189 hide_button.signal_clicked().connect (sigc::mem_fun(*this, &AutomationTimeAxisView::hide_clicked));
190 auto_button.signal_clicked().connect (sigc::mem_fun(*this, &AutomationTimeAxisView::auto_clicked));
192 controls_base_selected_name = X_("AutomationTrackControlsBaseSelected");
193 controls_base_unselected_name = X_("AutomationTrackControlsBase");
194 controls_ebox.set_name (controls_base_unselected_name);
196 XMLNode* xml_node = get_parent_with_state()->get_automation_child_xml_node (
197 _control->parameter());
200 set_state (*xml_node, Stateful::loading_state_version);
203 /* ask for notifications of any new RegionViews */
209 /* no regions, just a single line for the entire track (e.g. bus gain) */
211 boost::shared_ptr<AutomationLine> line(new AutomationLine (
212 ARDOUR::EventTypeMap::instance().to_symbol(_control->parameter()),
217 line->set_line_color (ARDOUR_UI::config()->canvasvar_ProcessorAutomationLine.get());
218 line->queue_reset ();
222 /* make sure labels etc. are correct */
224 automation_state_changed ();
225 ColorsChanged.connect (sigc::mem_fun (*this, &AutomationTimeAxisView::color_handler));
228 AutomationTimeAxisView::~AutomationTimeAxisView ()
233 AutomationTimeAxisView::auto_clicked ()
235 using namespace Menu_Helpers;
237 if (automation_menu == 0) {
238 automation_menu = manage (new Menu);
239 automation_menu->set_name ("ArdourContextMenu");
240 MenuList& items (automation_menu->items());
242 items.push_back (MenuElem (_("Manual"), sigc::bind (sigc::mem_fun(*this,
243 &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
244 items.push_back (MenuElem (_("Play"), sigc::bind (sigc::mem_fun(*this,
245 &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
246 items.push_back (MenuElem (_("Write"), sigc::bind (sigc::mem_fun(*this,
247 &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
248 items.push_back (MenuElem (_("Touch"), sigc::bind (sigc::mem_fun(*this,
249 &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
252 automation_menu->popup (1, gtk_get_current_event_time());
256 AutomationTimeAxisView::set_automation_state (AutoState state)
258 if (!ignore_state_request) {
260 _automatable->set_parameter_automation_state (_control->parameter(), state);
263 if (_route == _automatable) { // This is a time axis for route (not region) automation
264 _route->set_parameter_automation_state (_control->parameter(), state);
267 if (_control->list())
268 _control->alist()->set_automation_state(state);
273 _view->set_automation_state (state);
275 /* AutomationStreamViews don't signal when their automation state changes, so handle
276 our updates `manually'.
278 automation_state_changed ();
283 AutomationTimeAxisView::automation_state_changed ()
287 /* update button label */
290 state = _control->alist()->automation_state ();
292 state = _view->automation_state ();
297 switch (state & (Off|Play|Touch|Write)) {
299 auto_button.set_label (_("Manual"));
301 ignore_state_request = true;
302 auto_off_item->set_active (true);
303 auto_play_item->set_active (false);
304 auto_touch_item->set_active (false);
305 auto_write_item->set_active (false);
306 ignore_state_request = false;
310 auto_button.set_label (_("Play"));
311 if (auto_play_item) {
312 ignore_state_request = true;
313 auto_play_item->set_active (true);
314 auto_off_item->set_active (false);
315 auto_touch_item->set_active (false);
316 auto_write_item->set_active (false);
317 ignore_state_request = false;
321 auto_button.set_label (_("Write"));
322 if (auto_write_item) {
323 ignore_state_request = true;
324 auto_write_item->set_active (true);
325 auto_off_item->set_active (false);
326 auto_play_item->set_active (false);
327 auto_touch_item->set_active (false);
328 ignore_state_request = false;
332 auto_button.set_label (_("Touch"));
333 if (auto_touch_item) {
334 ignore_state_request = true;
335 auto_touch_item->set_active (true);
336 auto_off_item->set_active (false);
337 auto_play_item->set_active (false);
338 auto_write_item->set_active (false);
339 ignore_state_request = false;
343 auto_button.set_label (_("???"));
348 /** The interpolation style of our AutomationList has changed, so update */
350 AutomationTimeAxisView::interpolation_changed (AutomationList::InterpolationStyle s)
352 if (mode_line_item && mode_discrete_item) {
353 if (s == AutomationList::Discrete) {
354 mode_discrete_item->set_active(true);
355 mode_line_item->set_active(false);
357 mode_line_item->set_active(true);
358 mode_discrete_item->set_active(false);
363 /** A menu item has been selected to change our interpolation mode */
365 AutomationTimeAxisView::set_interpolation (AutomationList::InterpolationStyle style)
367 /* Tell our view's list, if we have one, otherwise tell our own.
368 * Everything else will be signalled back from that.
372 _view->set_interpolation (style);
374 _control->list()->set_interpolation (style);
379 AutomationTimeAxisView::clear_clicked ()
381 assert (_line || _view);
383 _session->begin_reversible_command (_("clear automation"));
391 _session->commit_reversible_command ();
392 _session->set_dirty ();
396 AutomationTimeAxisView::set_height (uint32_t h)
398 bool const changed = (height != (uint32_t) h) || first_call_to_set_height;
399 uint32_t const normal = preset_height (HeightNormal);
400 bool const changed_between_small_and_normal = ( (height < normal && h >= normal) || (height >= normal || h < normal) );
402 TimeAxisView* state_parent = get_parent_with_state ();
403 assert(state_parent);
404 XMLNode* xml_node = state_parent->get_automation_child_xml_node (_control->parameter());
406 TimeAxisView::set_height (h);
407 _base_rect->property_y2() = h;
410 _line->set_height(h);
414 _view->set_height(h);
415 _view->update_contents_height();
419 snprintf (buf, sizeof (buf), "%u", height);
421 xml_node->add_property ("height", buf);
424 if (changed_between_small_and_normal || first_call_to_set_height) {
426 first_call_to_set_height = false;
428 if (h >= preset_height (HeightNormal)) {
429 controls_table.remove (name_hbox);
432 if (plugname_packed) {
433 controls_table.remove (*plugname);
434 plugname_packed = false;
436 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
437 plugname_packed = true;
438 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
440 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
444 name_hbox.show_all ();
447 hide_button.show_all();
449 } else if (h >= preset_height (HeightSmall)) {
450 controls_table.remove (name_hbox);
452 if (plugname_packed) {
453 controls_table.remove (*plugname);
454 plugname_packed = false;
457 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
458 controls_table.hide_all ();
461 name_hbox.show_all ();
466 } else if (h >= preset_height (HeightNormal)) {
467 cerr << "track grown, but neither changed_between_small_and_normal nor first_call_to_set_height set!" << endl;
471 if (canvas_item_visible (_canvas_display)) {
472 /* only emit the signal if the height really changed and we were visible */
473 _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */
479 AutomationTimeAxisView::set_samples_per_unit (double spu)
481 TimeAxisView::set_samples_per_unit (spu);
488 _view->set_samples_per_unit (spu);
493 AutomationTimeAxisView::hide_clicked ()
495 // LAME fix for refreshing the hide button
496 hide_button.set_sensitive(false);
498 set_marked_for_display (false);
501 hide_button.set_sensitive(true);
505 AutomationTimeAxisView::build_display_menu ()
507 using namespace Menu_Helpers;
511 TimeAxisView::build_display_menu ();
513 /* now fill it with our stuff */
515 MenuList& items = display_menu->items();
517 items.push_back (MenuElem (_("Hide"), sigc::mem_fun(*this, &AutomationTimeAxisView::hide_clicked)));
518 items.push_back (SeparatorElem());
519 items.push_back (MenuElem (_("Clear"), sigc::mem_fun(*this, &AutomationTimeAxisView::clear_clicked)));
520 items.push_back (SeparatorElem());
524 Menu* auto_state_menu = manage (new Menu);
525 auto_state_menu->set_name ("ArdourContextMenu");
526 MenuList& as_items = auto_state_menu->items();
528 as_items.push_back (CheckMenuElem (_("Manual"), sigc::bind (
529 sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
531 auto_off_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
533 as_items.push_back (CheckMenuElem (_("Play"), sigc::bind (
534 sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
536 auto_play_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
538 as_items.push_back (CheckMenuElem (_("Write"), sigc::bind (
539 sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
540 (AutoState) Write)));
541 auto_write_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
543 as_items.push_back (CheckMenuElem (_("Touch"), sigc::bind (
544 sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
545 (AutoState) Touch)));
546 auto_touch_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
548 items.push_back (MenuElem (_("State"), *auto_state_menu));
552 /* current interpolation state */
553 AutomationList::InterpolationStyle const s = _view ? _view->interpolation() : _control->list()->interpolation ();
555 if (EventTypeMap::instance().is_midi_parameter(_control->parameter())) {
557 Menu* auto_mode_menu = manage (new Menu);
558 auto_mode_menu->set_name ("ArdourContextMenu");
559 MenuList& am_items = auto_mode_menu->items();
561 RadioMenuItem::Group group;
563 am_items.push_back (RadioMenuElem (group, _("Discrete"), sigc::bind (
564 sigc::mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
565 AutomationList::Discrete)));
566 mode_discrete_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
567 mode_discrete_item->set_active (s == AutomationList::Discrete);
569 am_items.push_back (RadioMenuElem (group, _("Linear"), sigc::bind (
570 sigc::mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
571 AutomationList::Linear)));
572 mode_line_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
573 mode_line_item->set_active (s == AutomationList::Linear);
575 items.push_back (MenuElem (_("Mode"), *auto_mode_menu));
578 /* make sure the automation menu state is correct */
580 automation_state_changed ();
581 interpolation_changed (s);
585 AutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* /*item*/, GdkEvent* /*event*/, nframes_t when, double y)
592 _canvas_display->w2i (x, y);
594 /* compute vertical fractional position */
596 y = 1.0 - (y / height);
600 _line->view_to_model_coord (x, y);
602 _session->begin_reversible_command (_("add automation event"));
603 XMLNode& before = _control->alist()->get_state();
605 _control->alist()->add (when, y);
607 XMLNode& after = _control->alist()->get_state();
608 _session->commit_reversible_command (new MementoCommand<ARDOUR::AutomationList>(*_control->alist(), &before, &after));
610 _session->set_dirty ();
614 AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
616 list<boost::shared_ptr<AutomationLine> > lines;
618 lines.push_back (_line);
620 lines = _view->get_lines ();
623 for (list<boost::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
624 cut_copy_clear_one (**i, selection, op);
629 AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
631 boost::shared_ptr<Evoral::ControlList> what_we_got;
632 boost::shared_ptr<AutomationList> alist (line.the_list());
634 XMLNode &before = alist->get_state();
636 /* convert time selection to automation list model coordinates */
637 const Evoral::TimeConverter<double, ARDOUR::sframes_t>& tc = line.time_converter ();
638 double const start = tc.from (selection.time.front().start - tc.origin_b ());
639 double const end = tc.from (selection.time.front().end - tc.origin_b ());
644 if ((what_we_got = alist->cut (start, end)) != 0) {
645 _editor.get_cut_buffer().add (what_we_got);
646 _session->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
650 if ((what_we_got = alist->copy (start, end)) != 0) {
651 _editor.get_cut_buffer().add (what_we_got);
656 if ((what_we_got = alist->cut (start, end)) != 0) {
657 _session->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
663 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
664 double when = (*x)->when;
665 double val = (*x)->value;
666 line.model_to_view_coord (when, val);
674 AutomationTimeAxisView::reset_objects (PointSelection& selection)
676 list<boost::shared_ptr<AutomationLine> > lines;
678 lines.push_back (_line);
680 lines = _view->get_lines ();
683 for (list<boost::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
684 reset_objects_one (**i, selection);
689 AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
691 boost::shared_ptr<AutomationList> alist(line.the_list());
693 _session->add_command (new MementoCommand<AutomationList>(*alist.get(), &alist->get_state(), 0));
695 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
697 if ((*i).track != this) {
701 alist->reset_range ((*i).start, (*i).end);
706 AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
708 list<boost::shared_ptr<AutomationLine> > lines;
710 lines.push_back (_line);
712 lines = _view->get_lines ();
715 for (list<boost::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
716 cut_copy_clear_objects_one (**i, selection, op);
721 AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
723 boost::shared_ptr<Evoral::ControlList> what_we_got;
724 boost::shared_ptr<AutomationList> alist(line.the_list());
726 XMLNode &before = alist->get_state();
728 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
730 if ((*i).track != this) {
736 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
737 _editor.get_cut_buffer().add (what_we_got);
738 _session->add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
742 if ((what_we_got = alist->copy ((*i).start, (*i).end)) != 0) {
743 _editor.get_cut_buffer().add (what_we_got);
748 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
749 _session->add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
758 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
759 double when = (*x)->when;
760 double val = (*x)->value;
761 line.model_to_view_coord (when, val);
768 /** Paste a selection.
769 * @param pos Position to paste to (session frames).
770 * @param times Number of times to paste.
771 * @param selection Selection to paste.
772 * @param nth Index of the AutomationList within the selection to paste from.
775 AutomationTimeAxisView::paste (framepos_t pos, float times, Selection& selection, size_t nth)
777 boost::shared_ptr<AutomationLine> line;
782 line = _view->paste_line (pos);
789 return paste_one (*line, pos, times, selection, nth);
793 AutomationTimeAxisView::paste_one (AutomationLine& line, framepos_t pos, float times, Selection& selection, size_t nth)
795 AutomationSelection::iterator p;
796 boost::shared_ptr<AutomationList> alist(line.the_list());
798 for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth) {}
800 if (p == selection.lines.end()) {
804 /* Make a copy of the list because we have to scale the
805 values from view coordinates to model coordinates, and we're
806 not supposed to modify the points in the selection.
809 AutomationList copy (**p);
811 for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
812 double when = (*x)->when;
813 double val = (*x)->value;
814 line.view_to_model_coord (when, val);
819 double const model_pos = line.time_converter().from (pos - line.time_converter().origin_b ());
821 XMLNode &before = alist->get_state();
822 alist->paste (copy, model_pos, times);
823 _session->add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
829 AutomationTimeAxisView::get_selectables (framepos_t start, framepos_t end, double top, double bot, list<Selectable*>& results)
831 if (!_line && !_view) {
835 if (touched (top, bot)) {
837 /* remember: this is X Window - coordinate space starts in upper left and moves down.
838 _y_position is the "origin" or "top" of the track.
841 /* bottom of our track */
842 double const mybot = _y_position + height;
847 if (_y_position >= top && mybot <= bot) {
849 /* _y_position is below top, mybot is above bot, so we're fully
858 /* top and bot are within _y_position .. mybot */
860 topfrac = 1.0 - ((top - _y_position) / height);
861 botfrac = 1.0 - ((bot - _y_position) / height);
866 _line->get_selectables (start, end, botfrac, topfrac, results);
868 _view->get_selectables (start, end, botfrac, topfrac, results);
874 AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
877 _line->get_inverted_selectables (sel, result);
882 AutomationTimeAxisView::set_selected_points (PointSelection& points)
885 _line->set_selected_points (points);
887 _view->set_selected_points (points);
892 AutomationTimeAxisView::clear_lines ()
895 _list_connections.drop_connections ();
899 AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
903 assert(line->the_list() == _control->list());
905 _control->alist()->automation_state_changed.connect (
906 _list_connections, invalidator (*this), boost::bind (&AutomationTimeAxisView::automation_state_changed, this), gui_context()
909 _control->alist()->InterpolationChanged.connect (
910 _list_connections, invalidator (*this), boost::bind (&AutomationTimeAxisView::interpolation_changed, this, _1), gui_context()
914 //_controller = AutomationController::create(_session, line->the_list(), _control);
916 line->set_height (height);
918 /* pick up the current state */
919 automation_state_changed ();
925 AutomationTimeAxisView::entered()
928 _line->track_entered();
932 AutomationTimeAxisView::exited ()
935 _line->track_exited();
939 AutomationTimeAxisView::color_handler ()
947 AutomationTimeAxisView::set_state (const XMLNode& node, int version)
949 TimeAxisView::set_state (node, version);
951 XMLProperty const * type = node.property ("automation-id");
952 if (type && type->value () == ARDOUR::EventTypeMap::instance().to_symbol (_control->parameter())) {
953 XMLProperty const * shown = node.property ("shown");
954 if (shown && shown->value () == "yes") {
955 set_marked_for_display (true);
956 _canvas_display->show (); /* FIXME: necessary? show_at? */
960 if (!_marked_for_display) {
968 AutomationTimeAxisView::get_state_node ()
970 TimeAxisView* state_parent = get_parent_with_state ();
973 return state_parent->get_automation_child_xml_node (_control->parameter());
980 AutomationTimeAxisView::update_extra_xml_shown (bool editor_shown)
982 XMLNode* xml_node = get_state_node();
984 xml_node->add_property ("shown", editor_shown ? "yes" : "no");
989 AutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
991 update_extra_xml_shown (true);
993 return TimeAxisView::show_at (y, nth, parent);
997 AutomationTimeAxisView::hide ()
999 update_extra_xml_shown (false);
1001 TimeAxisView::hide ();
1005 AutomationTimeAxisView::set_visibility (bool yn)
1007 bool changed = TimeAxisView::set_visibility (yn);
1010 get_state_node()->add_property ("shown", yn ? X_("yes") : X_("no"));
1016 /** @return true if this view has any automation data to display */
1018 AutomationTimeAxisView::has_automation () const
1020 return ( (_line && _line->npoints() > 0) || (_view && _view->has_automation()) );