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 "rgb_macros.h"
35 #include "automation_selectable.h"
36 #include "point_selection.h"
37 #include "canvas_impl.h"
42 using namespace ARDOUR;
45 using namespace Gtkmm2ext;
46 using namespace Editing;
48 Pango::FontDescription* AutomationTimeAxisView::name_font = 0;
49 bool AutomationTimeAxisView::have_name_font = false;
50 const string AutomationTimeAxisView::state_node_name = "AutomationChild";
53 /** \a a the automatable object this time axis is to display data for.
54 * For route/track automation (e.g. gain) pass the route for both \r and \a.
55 * For route child (e.g. plugin) automation, pass the child for \a.
56 * For region automation (e.g. MIDI CC), pass null for \a.
58 AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r,
59 boost::shared_ptr<Automatable> a, boost::shared_ptr<AutomationControl> c,
60 PublicEditor& e, TimeAxisView& parent, bool show_regions,
61 ArdourCanvas::Canvas& canvas, const string & nom, const string & nomparent)
63 TimeAxisView (s, e, &parent, canvas),
67 _controller(AutomationController::create(a, c->parameter(), c)),
69 _view (show_regions ? new AutomationStreamView(*this) : NULL),
71 clear_button (_("clear")),
72 auto_button (X_("")) /* force addition of a label */
74 if (!have_name_font) {
75 name_font = get_font_for_style (X_("AutomationTrackName"));
76 have_name_font = true;
84 mode_discrete_item = 0;
87 ignore_state_request = false;
88 first_call_to_set_height = true;
90 _base_rect = new SimpleRect(*canvas_display);
91 _base_rect->property_x1() = 0.0;
92 _base_rect->property_y1() = 0.0;
93 _base_rect->property_x2() = LONG_MAX - 2;
94 _base_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackOutline.get();
96 /* outline ends and bottom */
97 _base_rect->property_outline_what() = (guint32) (0x1|0x2|0x8);
98 _base_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackFill.get();
100 _base_rect->set_data ("trackview", this);
102 _base_rect->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_automation_track_event),
105 _base_rect->lower_to_bottom();
107 hide_button.add (*(manage (new Gtk::Image (::get_icon("hide")))));
109 auto_button.set_name ("TrackVisualButton");
110 clear_button.set_name ("TrackVisualButton");
111 hide_button.set_name ("TrackRemoveButton");
113 auto_button.unset_flags (Gtk::CAN_FOCUS);
114 clear_button.unset_flags (Gtk::CAN_FOCUS);
115 hide_button.unset_flags (Gtk::CAN_FOCUS);
117 controls_table.set_no_show_all();
119 ARDOUR_UI::instance()->tooltips().set_tip(auto_button, _("automation state"));
120 ARDOUR_UI::instance()->tooltips().set_tip(clear_button, _("clear track"));
121 ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("hide track"));
123 /* rearrange the name display */
125 /* we never show these for automation tracks, so make
126 life easier and remove them.
131 /* move the name label over a bit */
133 string shortpname = _name;
134 bool shortened = false;
137 shortpname = fit_to_pixels (_name, 60, *name_font, ignore_width, true);
139 if (shortpname != _name ){
143 name_label.set_text (shortpname);
144 name_label.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
146 if (nomparent.length()) {
148 /* limit the plug name string */
150 string pname = fit_to_pixels (nomparent, 60, *name_font, ignore_width, true);
151 if (pname != nomparent) {
155 plugname = new Label (pname);
156 plugname->set_name (X_("TrackPlugName"));
158 name_label.set_name (X_("TrackParameterName"));
159 controls_table.remove (name_hbox);
160 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
161 plugname_packed = true;
162 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
165 plugname_packed = false;
169 string tipname = nomparent;
170 if (!tipname.empty()) {
174 ARDOUR_UI::instance()->tooltips().set_tip(controls_ebox, tipname);
177 /* add the buttons */
178 controls_table.attach (hide_button, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
180 controls_table.attach (auto_button, 5, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
181 controls_table.attach (clear_button, 5, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
183 /* add bar controller */
184 controls_table.attach (*_controller.get(), 0, 8, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
186 controls_table.show_all ();
188 clear_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::clear_clicked));
189 hide_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::hide_clicked));
190 auto_button.signal_clicked().connect (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 controls_frame.set_shadow_type (Gtk::SHADOW_ETCHED_OUT);
198 XMLNode* xml_node = get_parent_with_state()->get_automation_child_xml_node (
199 _control->parameter());
202 set_state (*xml_node);
205 /* ask for notifications of any new RegionViews */
211 /* no regions, just a single line for the entire track (e.g. bus gain) */
214 boost::shared_ptr<AutomationLine> line(new AutomationLine (
215 ARDOUR::EventTypeMap::instance().to_symbol(_control->parameter()),
220 line->set_line_color (ARDOUR_UI::config()->canvasvar_ProcessorAutomationLine.get());
221 line->queue_reset ();
225 /* make sure labels etc. are correct */
227 automation_state_changed ();
228 ColorsChanged.connect (mem_fun (*this, &AutomationTimeAxisView::color_handler));
231 AutomationTimeAxisView::~AutomationTimeAxisView ()
236 AutomationTimeAxisView::auto_clicked ()
238 using namespace Menu_Helpers;
240 if (automation_menu == 0) {
241 automation_menu = manage (new Menu);
242 automation_menu->set_name ("ArdourContextMenu");
243 MenuList& items (automation_menu->items());
245 items.push_back (MenuElem (_("Manual"), bind (mem_fun(*this,
246 &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
247 items.push_back (MenuElem (_("Play"), bind (mem_fun(*this,
248 &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
249 items.push_back (MenuElem (_("Write"), bind (mem_fun(*this,
250 &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
251 items.push_back (MenuElem (_("Touch"), bind (mem_fun(*this,
252 &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
255 automation_menu->popup (1, gtk_get_current_event_time());
259 AutomationTimeAxisView::set_automation_state (AutoState state)
261 if (!ignore_state_request) {
262 if (_route == _automatable) { // This is a time axis for route (not region) automation
263 _route->set_parameter_automation_state (_control->parameter(), state);
266 if (_control->list())
267 _control->alist()->set_automation_state(state);
270 _view->set_automation_state (state);
274 AutomationTimeAxisView::automation_state_changed ()
278 /* update button label */
283 state = _control->alist()->automation_state ();
286 switch (state & (Off|Play|Touch|Write)) {
288 auto_button.set_label (_("Manual"));
290 ignore_state_request = true;
291 auto_off_item->set_active (true);
292 auto_play_item->set_active (false);
293 auto_touch_item->set_active (false);
294 auto_write_item->set_active (false);
295 ignore_state_request = false;
299 auto_button.set_label (_("Play"));
300 if (auto_play_item) {
301 ignore_state_request = true;
302 auto_play_item->set_active (true);
303 auto_off_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 (_("Write"));
311 if (auto_write_item) {
312 ignore_state_request = true;
313 auto_write_item->set_active (true);
314 auto_off_item->set_active (false);
315 auto_play_item->set_active (false);
316 auto_touch_item->set_active (false);
317 ignore_state_request = false;
321 auto_button.set_label (_("Touch"));
322 if (auto_touch_item) {
323 ignore_state_request = true;
324 auto_touch_item->set_active (true);
325 auto_off_item->set_active (false);
326 auto_play_item->set_active (false);
327 auto_write_item->set_active (false);
328 ignore_state_request = false;
332 auto_button.set_label (_("???"));
338 AutomationTimeAxisView::interpolation_changed ()
340 AutomationList::InterpolationStyle style = _control->list()->interpolation();
342 if (mode_line_item && mode_discrete_item) {
343 if (style == AutomationList::Discrete) {
344 mode_discrete_item->set_active(true);
345 mode_line_item->set_active(false);
347 mode_line_item->set_active(true);
348 mode_discrete_item->set_active(false);
353 _line->set_interpolation(style);
357 AutomationTimeAxisView::set_interpolation (AutomationList::InterpolationStyle style)
359 _control->list()->set_interpolation(style);
361 _line->set_interpolation(style);
365 AutomationTimeAxisView::clear_clicked ()
367 _session.begin_reversible_command (_("clear automation"));
370 _session.commit_reversible_command ();
374 AutomationTimeAxisView::set_height (uint32_t h)
376 bool changed = (height != (uint32_t) h) || first_call_to_set_height;
377 bool changed_between_small_and_normal = ( (height < hNormal && h >= hNormal) || (height >= hNormal || h < hNormal) );
379 TimeAxisView* state_parent = get_parent_with_state ();
380 assert(state_parent);
381 XMLNode* xml_node = state_parent->get_automation_child_xml_node (_control->parameter());
383 TimeAxisView::set_height (h);
384 _base_rect->property_y2() = h;
387 _line->set_height(h);
390 _view->set_height(h);
391 _view->update_contents_height();
395 snprintf (buf, sizeof (buf), "%u", height);
397 xml_node->add_property ("height", buf);
400 if (changed_between_small_and_normal || first_call_to_set_height) {
402 first_call_to_set_height = false;
405 controls_table.remove (name_hbox);
408 if (plugname_packed) {
409 controls_table.remove (*plugname);
410 plugname_packed = false;
412 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
413 plugname_packed = true;
414 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
416 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
420 name_hbox.show_all ();
424 hide_button.show_all();
426 } else if (h >= hSmall) {
427 controls_table.remove (name_hbox);
429 if (plugname_packed) {
430 controls_table.remove (*plugname);
431 plugname_packed = false;
434 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
435 controls_table.hide_all ();
438 name_hbox.show_all ();
444 } else if (h >= hNormal){
445 cerr << "track grown, but neither changed_between_small_and_normal nor first_call_to_set_height set!" << endl;
449 /* only emit the signal if the height really changed */
450 _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */
455 AutomationTimeAxisView::set_samples_per_unit (double spu)
457 TimeAxisView::set_samples_per_unit (spu);
463 _view->set_samples_per_unit (spu);
467 AutomationTimeAxisView::hide_clicked ()
469 // LAME fix for refreshing the hide button
470 hide_button.set_sensitive(false);
472 set_marked_for_display (false);
475 hide_button.set_sensitive(true);
479 AutomationTimeAxisView::build_display_menu ()
481 using namespace Menu_Helpers;
483 /* get the size menu ready */
489 TimeAxisView::build_display_menu ();
491 /* now fill it with our stuff */
493 MenuList& items = display_menu->items();
495 items.push_back (MenuElem (_("Height"), *size_menu));
496 items.push_back (SeparatorElem());
497 items.push_back (MenuElem (_("Hide"), mem_fun(*this, &AutomationTimeAxisView::hide_clicked)));
498 items.push_back (SeparatorElem());
499 items.push_back (MenuElem (_("Clear"), mem_fun(*this, &AutomationTimeAxisView::clear_clicked)));
500 items.push_back (SeparatorElem());
504 Menu* auto_state_menu = manage (new Menu);
505 auto_state_menu->set_name ("ArdourContextMenu");
506 MenuList& as_items = auto_state_menu->items();
508 as_items.push_back (CheckMenuElem (_("Manual"),
509 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
510 auto_off_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
512 as_items.push_back (CheckMenuElem (_("Play"),
513 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
514 auto_play_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
516 as_items.push_back (CheckMenuElem (_("Write"),
517 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
518 auto_write_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
520 as_items.push_back (CheckMenuElem (_("Touch"),
521 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
522 auto_touch_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
524 items.push_back (MenuElem (_("State"), *auto_state_menu));
528 if (_control->parameter().type() == MidiCCAutomation) {
529 Menu* auto_mode_menu = manage (new Menu);
530 auto_mode_menu->set_name ("ArdourContextMenu");
531 MenuList& am_items = auto_mode_menu->items();
533 RadioMenuItem::Group group;
535 am_items.push_back (RadioMenuElem (group, _("Discrete"), bind (
536 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
537 AutomationList::Discrete)));
538 mode_discrete_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
539 //mode_discrete_item->set_active(_control->list()->interpolation() == AutomationList::Discrete);
541 am_items.push_back (RadioMenuElem (group, _("Line"), bind (
542 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
543 AutomationList::Linear)));
544 mode_line_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
545 //mode_line_item->set_active(_control->list()->interpolation() == AutomationList::Linear);
547 items.push_back (MenuElem (_("Mode"), *auto_mode_menu));
550 /* make sure the automation menu state is correct */
552 automation_state_changed ();
553 interpolation_changed ();
557 AutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEvent* event, nframes_t when, double y)
564 canvas_display->w2i (x, y);
566 /* compute vertical fractional position */
568 y = 1.0 - (y / height);
572 _line->view_to_model_y (y);
574 _session.begin_reversible_command (_("add automation event"));
575 XMLNode& before = _control->alist()->get_state();
577 _control->alist()->add (when, y);
579 XMLNode& after = _control->alist()->get_state();
580 _session.commit_reversible_command (new MementoCommand<ARDOUR::AutomationList>(*_control->alist(), &before, &after));
582 _session.set_dirty ();
587 AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
589 return (_line ? cut_copy_clear_one (*_line, selection, op) : false);
593 AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
595 boost::shared_ptr<Evoral::ControlList> what_we_got;
596 boost::shared_ptr<AutomationList> alist (line.the_list());
599 XMLNode &before = alist->get_state();
603 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
604 editor.get_cut_buffer().add (what_we_got);
605 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
610 if ((what_we_got = alist->copy (selection.time.front().start, selection.time.front().end)) != 0) {
611 editor.get_cut_buffer().add (what_we_got);
616 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
617 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
624 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
625 double foo = (*x)->value;
626 line.model_to_view_y (foo);
635 AutomationTimeAxisView::reset_objects (PointSelection& selection)
637 reset_objects_one (*_line, selection);
641 AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
643 boost::shared_ptr<AutomationList> alist(line.the_list());
645 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &alist->get_state(), 0));
647 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
649 if (&(*i).track != this) {
653 alist->reset_range ((*i).start, (*i).end);
658 AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
660 return cut_copy_clear_objects_one (*_line, selection, op);
664 AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
666 boost::shared_ptr<Evoral::ControlList> what_we_got;
667 boost::shared_ptr<AutomationList> alist(line.the_list());
670 XMLNode &before = alist->get_state();
672 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
674 if (&(*i).track != this) {
680 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
681 editor.get_cut_buffer().add (what_we_got);
682 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
687 if ((what_we_got = alist->copy ((*i).start, (*i).end)) != 0) {
688 editor.get_cut_buffer().add (what_we_got);
693 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
694 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
704 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
705 double foo = (*x)->value;
706 line.model_to_view_y (foo);
715 AutomationTimeAxisView::paste (nframes_t pos, float times, Selection& selection, size_t nth)
717 return paste_one (*_line, pos, times, selection, nth);
721 AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float times, Selection& selection, size_t nth)
723 AutomationSelection::iterator p;
724 boost::shared_ptr<AutomationList> alist(line.the_list());
726 for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth);
728 if (p == selection.lines.end()) {
732 /* Make a copy of the list because we have to scale the
733 values from view coordinates to model coordinates, and we're
734 not supposed to modify the points in the selection.
737 AutomationList copy (**p);
739 for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
740 double foo = (*x)->value;
741 line.view_to_model_y (foo);
745 XMLNode &before = alist->get_state();
746 alist->paste (copy, pos, times);
747 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
753 AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results)
755 if (_line && touched (top, bot)) {
759 /* remember: this is X Window - coordinate space starts in upper left and moves down.
760 y_position is the "origin" or "top" of the track.
763 double mybot = y_position + height;
765 if (y_position >= top && mybot <= bot) {
767 /* y_position is below top, mybot is above bot, so we're fully
776 /* top and bot are within y_position .. mybot */
778 topfrac = 1.0 - ((top - y_position) / height);
779 botfrac = 1.0 - ((bot - y_position) / height);
783 _line->get_selectables (start, end, botfrac, topfrac, results);
788 AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
791 _line->get_inverted_selectables (sel, result);
795 AutomationTimeAxisView::set_selected_points (PointSelection& points)
798 _line->set_selected_points (points);
802 AutomationTimeAxisView::clear_lines ()
805 automation_connection.disconnect ();
809 AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
813 assert(line->the_list() == _control->list());
815 automation_connection = _control->alist()->automation_state_changed.connect
816 (mem_fun(*this, &AutomationTimeAxisView::automation_state_changed));
819 //_controller = AutomationController::create(_session, line->the_list(), _control);
821 line->set_height (height);
823 /* pick up the current state */
824 automation_state_changed ();
830 AutomationTimeAxisView::entered()
833 _line->track_entered();
837 AutomationTimeAxisView::exited ()
840 _line->track_exited();
844 AutomationTimeAxisView::set_colors ()
846 for (list<GhostRegion*>::iterator i=ghosts.begin(); i != ghosts.end(); i++ ) {
855 AutomationTimeAxisView::color_handler ()
863 AutomationTimeAxisView::set_state (const XMLNode& node)
865 TimeAxisView::set_state (node);
867 XMLProperty const * type = node.property ("automation-id");
868 if (type && type->value () == ARDOUR::EventTypeMap::instance().to_symbol (_control->parameter())) {
869 XMLProperty const * shown = node.property ("shown");
870 if (shown && shown->value () == "yes") {
871 set_marked_for_display (true);
872 canvas_display->show (); /* FIXME: necessary? show_at? */
876 if (!_marked_for_display) {
884 AutomationTimeAxisView::get_state_node ()
886 TimeAxisView* state_parent = get_parent_with_state ();
889 return state_parent->get_automation_child_xml_node (_control->parameter());
896 AutomationTimeAxisView::update_extra_xml_shown (bool editor_shown)
898 XMLNode* xml_node = get_state_node();
900 xml_node->add_property ("shown", editor_shown ? "yes" : "no");
905 AutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
907 update_extra_xml_shown (true);
909 return TimeAxisView::show_at (y, nth, parent);
913 AutomationTimeAxisView::hide ()
915 update_extra_xml_shown (false);
917 TimeAxisView::hide ();