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 <ardour/route.h>
22 #include <ardour/automation_control.h>
23 #include <pbd/memento_command.h>
24 #include <gtkmm2ext/barcontroller.h>
26 #include "ardour_ui.h"
27 #include "automation_time_axis.h"
28 #include "automation_streamview.h"
29 #include "route_time_axis.h"
30 #include "automation_line.h"
31 #include "public_editor.h"
32 #include "simplerect.h"
33 #include "selection.h"
34 #include "ghostregion.h"
35 #include "rgb_macros.h"
36 #include "automation_selectable.h"
37 #include "point_selection.h"
38 #include "canvas_impl.h"
43 using namespace ARDOUR;
46 using namespace Gtkmm2ext;
47 using namespace Editing;
49 Pango::FontDescription* AutomationTimeAxisView::name_font = 0;
50 bool AutomationTimeAxisView::have_name_font = false;
51 const string AutomationTimeAxisView::state_node_name = "AutomationChild";
53 AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r,
54 boost::shared_ptr<Automatable> a, boost::shared_ptr<AutomationControl> c,
55 PublicEditor& e, TimeAxisView& parent, bool show_regions,
56 ArdourCanvas::Canvas& canvas, const string & nom, const string & nomparent)
59 TimeAxisView (s, e, &parent, canvas),
63 _controller(AutomationController::create(a, c->list(), c)),
65 _view (show_regions ? new AutomationStreamView(*this) : NULL),
67 height_button (_("h")),
68 clear_button (_("clear")),
69 auto_button (X_("")) /* force addition of a label */
71 if (!have_name_font) {
72 name_font = get_font_for_style (X_("AutomationTrackName"));
73 have_name_font = true;
77 in_destructor = false;
82 mode_discrete_item = 0;
85 ignore_state_request = false;
86 first_call_to_set_height = true;
88 _base_rect = new SimpleRect(*canvas_display);
89 _base_rect->property_x1() = 0.0;
90 _base_rect->property_y1() = 0.0;
91 _base_rect->property_x2() = editor.frame_to_pixel (max_frames);
92 _base_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackOutline.get();
94 /* outline ends and bottom */
95 _base_rect->property_outline_what() = (guint32) (0x1|0x2|0x8);
96 _base_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackFill.get();
98 _base_rect->set_data ("trackview", this);
100 _base_rect->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_automation_track_event),
103 _base_rect->lower_to_bottom();
105 hide_button.add (*(manage (new Gtk::Image (::get_icon("hide")))));
107 height_button.set_name ("TrackSizeButton");
108 auto_button.set_name ("TrackVisualButton");
109 clear_button.set_name ("TrackVisualButton");
110 hide_button.set_name ("TrackRemoveButton");
112 controls_table.set_no_show_all();
114 ARDOUR_UI::instance()->tooltips().set_tip(height_button, _("track height"));
115 ARDOUR_UI::instance()->tooltips().set_tip(auto_button, _("automation state"));
116 ARDOUR_UI::instance()->tooltips().set_tip(clear_button, _("clear track"));
117 ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("hide track"));
119 /* rearrange the name display */
121 /* we never show these for automation tracks, so make
122 life easier and remove them.
127 /* move the name label over a bit */
129 string shortpname = _name;
130 bool shortened = false;
133 shortpname = fit_to_pixels (_name, 60, *name_font, ignore_width, true);
135 if (shortpname != _name ){
139 name_label.set_text (shortpname);
140 name_label.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
142 if (nomparent.length()) {
144 /* limit the plug name string */
146 string pname = fit_to_pixels (nomparent, 60, *name_font, ignore_width, true);
147 if (pname != nomparent) {
151 plugname = new Label (pname);
152 plugname->set_name (X_("TrackPlugName"));
154 name_label.set_name (X_("TrackParameterName"));
155 controls_table.remove (name_hbox);
156 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
157 plugname_packed = true;
158 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
161 plugname_packed = false;
165 string tipname = nomparent;
166 if (!tipname.empty()) {
170 ARDOUR_UI::instance()->tooltips().set_tip(controls_ebox, tipname);
173 /* add the buttons */
174 controls_table.attach (hide_button, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
175 controls_table.attach (height_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
177 controls_table.attach (auto_button, 5, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
178 controls_table.attach (clear_button, 5, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
180 /* add bar controller */
181 controls_table.attach (*_controller.get(), 0, 8, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
183 controls_table.show_all ();
185 height_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::height_clicked));
186 clear_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::clear_clicked));
187 hide_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::hide_clicked));
188 auto_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::auto_clicked));
190 controls_base_selected_name = X_("AutomationTrackControlsBaseSelected");
191 controls_base_unselected_name = X_("AutomationTrackControlsBase");
192 controls_ebox.set_name (controls_base_unselected_name);
194 controls_frame.set_shadow_type (Gtk::SHADOW_ETCHED_OUT);
196 XMLNode* xml_node = get_parent_with_state()->get_automation_child_xml_node (
197 _control->parameter());
200 set_state (*xml_node);
203 /* ask for notifications of any new RegionViews */
209 /* no regions, just a single line for the entire track (e.g. bus gain) */
212 boost::shared_ptr<AutomationLine> line(new AutomationLine (
213 _control->parameter().to_string(),
218 line->set_line_color (ARDOUR_UI::config()->canvasvar_ProcessorAutomationLine.get());
219 line->queue_reset ();
223 /* make sure labels etc. are correct */
225 automation_state_changed ();
226 ColorsChanged.connect (mem_fun (*this, &AutomationTimeAxisView::color_handler));
229 AutomationTimeAxisView::~AutomationTimeAxisView ()
231 in_destructor = true;
233 for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
239 AutomationTimeAxisView::auto_clicked ()
241 using namespace Menu_Helpers;
243 if (automation_menu == 0) {
244 automation_menu = manage (new Menu);
245 automation_menu->set_name ("ArdourContextMenu");
246 MenuList& items (automation_menu->items());
248 items.push_back (MenuElem (_("Manual"),
249 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
250 items.push_back (MenuElem (_("Play"),
251 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
252 items.push_back (MenuElem (_("Write"),
253 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
254 items.push_back (MenuElem (_("Touch"),
255 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
258 automation_menu->popup (1, gtk_get_current_event_time());
262 AutomationTimeAxisView::set_automation_state (AutoState state)
264 if (!ignore_state_request) {
265 if (_route == _automatable) { // FIXME: ew
266 _route->set_parameter_automation_state (
267 _control->parameter(),
271 _control->list()->set_automation_state(state);
277 AutomationTimeAxisView::automation_state_changed ()
281 /* update button label */
286 state = _control->list()->automation_state ();
289 switch (state & (Off|Play|Touch|Write)) {
291 auto_button.set_label (_("Manual"));
293 ignore_state_request = true;
294 auto_off_item->set_active (true);
295 auto_play_item->set_active (false);
296 auto_touch_item->set_active (false);
297 auto_write_item->set_active (false);
298 ignore_state_request = false;
302 auto_button.set_label (_("Play"));
303 if (auto_play_item) {
304 ignore_state_request = true;
305 auto_play_item->set_active (true);
306 auto_off_item->set_active (false);
307 auto_touch_item->set_active (false);
308 auto_write_item->set_active (false);
309 ignore_state_request = false;
313 auto_button.set_label (_("Write"));
314 if (auto_write_item) {
315 ignore_state_request = true;
316 auto_write_item->set_active (true);
317 auto_off_item->set_active (false);
318 auto_play_item->set_active (false);
319 auto_touch_item->set_active (false);
320 ignore_state_request = false;
324 auto_button.set_label (_("Touch"));
325 if (auto_touch_item) {
326 ignore_state_request = true;
327 auto_touch_item->set_active (true);
328 auto_off_item->set_active (false);
329 auto_play_item->set_active (false);
330 auto_write_item->set_active (false);
331 ignore_state_request = false;
335 auto_button.set_label (_("???"));
341 AutomationTimeAxisView::interpolation_changed ()
343 AutomationList::InterpolationStyle style = _control->list()->interpolation();
345 if (mode_line_item && mode_discrete_item) {
346 if (style == AutomationList::Discrete) {
347 mode_discrete_item->set_active(true);
348 mode_line_item->set_active(false);
350 mode_line_item->set_active(true);
351 mode_discrete_item->set_active(false);
356 _line->set_interpolation(style);
360 AutomationTimeAxisView::set_interpolation (AutomationList::InterpolationStyle style)
362 _control->list()->set_interpolation(style);
364 _line->set_interpolation(style);
368 AutomationTimeAxisView::height_clicked ()
374 AutomationTimeAxisView::clear_clicked ()
376 _session.begin_reversible_command (_("clear automation"));
379 _session.commit_reversible_command ();
383 AutomationTimeAxisView::set_height (TrackHeight ht)
385 uint32_t h = height_to_pixels (ht);
386 bool changed = (height != (uint32_t) h) || first_call_to_set_height;
388 if (first_call_to_set_height)
389 first_call_to_set_height = false;
391 TimeAxisView::set_height (ht);
392 _base_rect->property_y2() = h;
395 _line->set_y_position_and_height (0, h);
398 _view->set_height(h);
399 _view->update_contents_y_position_and_height();
402 for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
406 TimeAxisView* state_parent = get_parent_with_state ();
407 assert(state_parent);
409 XMLNode* xml_node = state_parent->get_automation_child_xml_node(_control->parameter());
414 xml_node->add_property ("track_height", "largest");
418 xml_node->add_property ("track_height", "large");
422 xml_node->add_property ("track_height", "larger");
426 xml_node->add_property ("track_height", "normal");
430 xml_node->add_property ("track_height", "smaller");
434 xml_node->add_property ("track_height", "small");
442 _controller->show ();
448 controls_table.remove (name_hbox);
451 if (plugname_packed) {
452 controls_table.remove (*plugname);
453 plugname_packed = false;
455 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
456 plugname_packed = true;
457 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
459 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
463 name_hbox.show_all ();
466 height_button.show();
468 hide_button.show_all();
476 controls_table.remove (name_hbox);
478 if (plugname_packed) {
479 controls_table.remove (*plugname);
480 plugname_packed = false;
483 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
484 controls_table.hide_all ();
487 name_hbox.show_all ();
490 height_button.hide();
497 /* only emit the signal if the height really changed */
498 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
503 AutomationTimeAxisView::set_samples_per_unit (double spu)
505 TimeAxisView::set_samples_per_unit (spu);
511 _view->set_samples_per_unit (spu);
515 AutomationTimeAxisView::hide_clicked ()
517 // LAME fix for refreshing the hide button
518 hide_button.set_sensitive(false);
520 set_marked_for_display (false);
523 hide_button.set_sensitive(true);
527 AutomationTimeAxisView::build_display_menu ()
529 using namespace Menu_Helpers;
531 /* get the size menu ready */
537 TimeAxisView::build_display_menu ();
539 /* now fill it with our stuff */
541 MenuList& items = display_menu->items();
543 items.push_back (MenuElem (_("Height"), *size_menu));
544 items.push_back (SeparatorElem());
545 items.push_back (MenuElem (_("Hide"), mem_fun(*this, &AutomationTimeAxisView::hide_clicked)));
546 items.push_back (SeparatorElem());
547 items.push_back (MenuElem (_("Clear"), mem_fun(*this, &AutomationTimeAxisView::clear_clicked)));
548 items.push_back (SeparatorElem());
552 Menu* auto_state_menu = manage (new Menu);
553 auto_state_menu->set_name ("ArdourContextMenu");
554 MenuList& as_items = auto_state_menu->items();
556 as_items.push_back (CheckMenuElem (_("Manual"),
557 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
558 auto_off_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
560 as_items.push_back (CheckMenuElem (_("Play"),
561 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
562 auto_play_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
564 as_items.push_back (CheckMenuElem (_("Write"),
565 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
566 auto_write_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
568 as_items.push_back (CheckMenuElem (_("Touch"),
569 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
570 auto_touch_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
572 items.push_back (MenuElem (_("State"), *auto_state_menu));
576 if (_control->parameter().type() == MidiCCAutomation) {
577 Menu* auto_mode_menu = manage (new Menu);
578 auto_mode_menu->set_name ("ArdourContextMenu");
579 MenuList& am_items = auto_mode_menu->items();
581 RadioMenuItem::Group group;
583 am_items.push_back (RadioMenuElem (group, _("Discrete"), bind (
584 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
585 AutomationList::Discrete)));
586 mode_discrete_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
587 //mode_discrete_item->set_active(_control->list()->interpolation() == AutomationList::Discrete);
589 am_items.push_back (RadioMenuElem (group, _("Line"), bind (
590 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
591 AutomationList::Linear)));
592 mode_line_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
593 //mode_line_item->set_active(_control->list()->interpolation() == AutomationList::Linear);
595 items.push_back (MenuElem (_("Mode"), *auto_mode_menu));
598 /* make sure the automation menu state is correct */
600 automation_state_changed ();
601 interpolation_changed ();
605 AutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEvent* event, nframes_t when, double y)
612 canvas_display->w2i (x, y);
614 /* compute vertical fractional position */
616 y = 1.0 - (y / height);
620 _line->view_to_model_y (y);
622 _session.begin_reversible_command (_("add automation event"));
623 XMLNode& before = _control->list()->get_state();
625 _control->list()->add (when, y);
627 XMLNode& after = _control->list()->get_state();
628 _session.commit_reversible_command (new MementoCommand<ARDOUR::AutomationList>(*_control->list().get(), &before, &after));
630 _session.set_dirty ();
635 AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
637 return cut_copy_clear_one (*_line, selection, op);
641 AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
643 AutomationList* what_we_got = 0;
644 boost::shared_ptr<AutomationList> alist (line.the_list());
647 XMLNode &before = alist->get_state();
651 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
652 editor.get_cut_buffer().add (what_we_got);
653 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
658 if ((what_we_got = alist->copy (selection.time.front().start, selection.time.front().end)) != 0) {
659 editor.get_cut_buffer().add (what_we_got);
664 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
665 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
674 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
675 double foo = (*x)->value;
676 line.model_to_view_y (foo);
685 AutomationTimeAxisView::reset_objects (PointSelection& selection)
687 reset_objects_one (*_line, selection);
691 AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
693 boost::shared_ptr<AutomationList> alist(line.the_list());
695 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &alist->get_state(), 0));
697 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
699 if (&(*i).track != this) {
703 alist->reset_range ((*i).start, (*i).end);
708 AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
710 return cut_copy_clear_objects_one (*_line, selection, op);
714 AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
716 AutomationList* what_we_got = 0;
717 boost::shared_ptr<AutomationList> alist(line.the_list());
720 XMLNode &before = alist->get_state();
722 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
724 if (&(*i).track != this) {
730 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
731 editor.get_cut_buffer().add (what_we_got);
732 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
737 if ((what_we_got = alist->copy ((*i).start, (*i).end)) != 0) {
738 editor.get_cut_buffer().add (what_we_got);
743 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
744 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
756 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
757 double foo = (*x)->value;
758 line.model_to_view_y (foo);
767 AutomationTimeAxisView::paste (nframes_t pos, float times, Selection& selection, size_t nth)
769 return paste_one (*_line, pos, times, selection, nth);
773 AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float times, Selection& selection, size_t nth)
775 AutomationSelection::iterator p;
776 boost::shared_ptr<AutomationList> alist(line.the_list());
778 for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth);
780 if (p == selection.lines.end()) {
784 /* Make a copy of the list because we have to scale the
785 values from view coordinates to model coordinates, and we're
786 not supposed to modify the points in the selection.
789 AutomationList copy (**p);
791 for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
792 double foo = (*x)->value;
793 line.view_to_model_y (foo);
797 XMLNode &before = alist->get_state();
798 alist->paste (copy, pos, times);
799 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
805 AutomationTimeAxisView::add_ghost (GhostRegion* gr)
807 ghosts.push_back (gr);
808 gr->GoingAway.connect (mem_fun(*this, &AutomationTimeAxisView::remove_ghost));
812 AutomationTimeAxisView::remove_ghost (GhostRegion* gr)
818 list<GhostRegion*>::iterator i;
820 for (i = ghosts.begin(); i != ghosts.end(); ++i) {
829 AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results)
831 if (_line && touched (top, bot)) {
835 /* remember: this is X Window - coordinate space starts in upper left and moves down.
836 y_position is the "origin" or "top" of the track.
839 double mybot = y_position + height;
841 if (y_position >= top && mybot <= bot) {
843 /* y_position is below top, mybot is above bot, so we're fully
852 /* top and bot are within y_position .. mybot */
854 topfrac = 1.0 - ((top - y_position) / height);
855 botfrac = 1.0 - ((bot - y_position) / height);
859 _line->get_selectables (start, end, botfrac, topfrac, results);
864 AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
867 _line->get_inverted_selectables (sel, result);
871 AutomationTimeAxisView::set_selected_points (PointSelection& points)
874 _line->set_selected_points (points);
878 AutomationTimeAxisView::clear_lines ()
881 automation_connection.disconnect ();
885 AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
889 assert(line->the_list() == _control->list());
891 automation_connection = _control->list()->automation_state_changed.connect
892 (mem_fun(*this, &AutomationTimeAxisView::automation_state_changed));
895 //_controller = AutomationController::create(_session, line->the_list(), _control);
897 line->set_y_position_and_height (0, height);
899 /* pick up the current state */
900 automation_state_changed ();
906 AutomationTimeAxisView::entered()
909 _line->track_entered();
913 AutomationTimeAxisView::exited ()
916 _line->track_exited();
920 AutomationTimeAxisView::set_colors ()
922 for (list<GhostRegion*>::iterator i=ghosts.begin(); i != ghosts.end(); i++ ) {
931 AutomationTimeAxisView::color_handler ()
937 AutomationTimeAxisView::set_state (const XMLNode& node)
939 TimeAxisView::set_state (node);
942 XMLNodeConstIterator iter;
944 kids = node.children ();
946 for (iter = kids.begin(); iter != kids.end(); ++iter) {
948 if ((*iter)->name() == state_node_name) {
949 XMLProperty* type = (*iter)->property("automation-id");
951 if (type && type->value() == _control->parameter().to_string()) {
952 XMLProperty *shown = (*iter)->property("shown_editor");
954 if (shown && shown->value() == "yes") {
955 set_marked_for_display(true);
956 canvas_display->show(); /* FIXME: necessary? show_at? */
963 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();
983 xml_node->add_property ("shown", editor_shown ? "yes" : "no");
987 AutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
989 update_extra_xml_shown (true);
991 return TimeAxisView::show_at (y, nth, parent);
995 AutomationTimeAxisView::hide ()
997 update_extra_xml_shown (false);
999 TimeAxisView::hide ();