ardour
route_time_axis.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006 Paul Davis
3 
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.
8 
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.
13 
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.
17 */
18 
19 #include <cstdlib>
20 #include <cmath>
21 #include <cassert>
22 
23 #include <algorithm>
24 #include <string>
25 #include <vector>
26 #include <map>
27 #include <utility>
28 
29 #include <sigc++/bind.h>
30 
31 #include "pbd/error.h"
32 #include "pbd/stl_delete.h"
33 #include "pbd/whitespace.h"
34 #include "pbd/memento_command.h"
35 #include "pbd/enumwriter.h"
37 
38 #include <gtkmm/menu.h>
39 #include <gtkmm/menuitem.h>
40 #include <gtkmm2ext/gtk_ui.h>
41 #include <gtkmm2ext/selector.h>
43 #include <gtkmm2ext/utils.h>
44 
45 #include "ardour/amp.h"
46 #include "ardour/meter.h"
47 #include "ardour/event_type_map.h"
48 #include "ardour/pannable.h"
49 #include "ardour/panner.h"
50 #include "ardour/processor.h"
51 #include "ardour/profile.h"
52 #include "ardour/route_group.h"
53 #include "ardour/session.h"
55 
56 #include "evoral/Parameter.hpp"
57 
58 #include "canvas/debug.h"
59 
60 #include "ardour_ui.h"
61 #include "ardour_button.h"
62 #include "debug.h"
63 #include "global_signals.h"
64 #include "route_time_axis.h"
65 #include "automation_time_axis.h"
66 #include "enums.h"
67 #include "gui_thread.h"
68 #include "item_counts.h"
69 #include "keyboard.h"
70 #include "paste_context.h"
71 #include "playlist_selector.h"
72 #include "point_selection.h"
73 #include "prompter.h"
74 #include "public_editor.h"
75 #include "region_view.h"
76 #include "rgb_macros.h"
77 #include "selection.h"
78 #include "streamview.h"
79 #include "utils.h"
80 #include "route_group_menu.h"
81 
82 #include "ardour/track.h"
83 
84 #include "i18n.h"
85 
86 using namespace ARDOUR;
87 using namespace ARDOUR_UI_UTILS;
88 using namespace PBD;
89 using namespace Gtkmm2ext;
90 using namespace Gtk;
91 using namespace Editing;
92 using namespace std;
93 using std::list;
94 
95 RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session* sess, ArdourCanvas::Canvas& canvas)
96  : AxisView(sess)
97  , RouteUI(sess)
98  , TimeAxisView(sess,ed,(TimeAxisView*) 0, canvas)
99  , _view (0)
100  , parent_canvas (canvas)
101  , no_redraw (false)
102  , button_table (3, 3)
103  , route_group_button (S_("RTAV|G"))
104  , playlist_button (S_("RTAV|P"))
105  , automation_button (S_("RTAV|A"))
106  , automation_action_menu (0)
107  , plugins_submenu_item (0)
108  , route_group_menu (0)
109  , playlist_action_menu (0)
110  , mode_menu (0)
111  , color_mode_menu (0)
112  , gm (sess, true, 75, 14)
113  , _ignore_set_layer_display (false)
114  , gain_automation_item(NULL)
115  , trim_automation_item(NULL)
116  , mute_automation_item(NULL)
117  , pan_automation_item(NULL)
118 {
119  number_label.set_name("tracknumber label");
121  number_label.set_alignment(.5, .5);
123 
124  sess->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::parameter_changed, this, _1), gui_context());
125 }
126 
127 void
129 {
130  RouteUI::set_route (rt);
131 
132  CANVAS_DEBUG_NAME (_canvas_display, string_compose ("main for %1", rt->name()));
133  CANVAS_DEBUG_NAME (selection_group, string_compose ("selections for %1", rt->name()));
134  CANVAS_DEBUG_NAME (_ghost_group, string_compose ("ghosts for %1", rt->name()));
135 
136  int meter_width = 3;
137  if (_route && _route->shared_peak_meter()->input_streams().n_total() == 1) {
138  meter_width = 6;
139  }
141  gm.get_level_meter().set_no_show_all();
142  gm.get_level_meter().setup_meters(50, meter_width);
144 
145  string str = gui_property ("height");
146  if (!str.empty()) {
147  set_height (atoi (str));
148  } else {
150  }
151 
152  if (!_route->is_auditioner()) {
153  if (gui_property ("visible").empty()) {
154  set_gui_property ("visible", true);
155  }
156  } else {
157  set_gui_property ("visible", false);
158  }
159 
160  timestretch_rect = 0;
161  no_redraw = false;
162 
163  ignore_toggle = false;
164 
165  route_group_button.set_name ("route button");
166  playlist_button.set_name ("route button");
167  automation_button.set_name ("route button");
168 
169  route_group_button.signal_button_release_event().connect (sigc::mem_fun(*this, &RouteTimeAxisView::route_group_click), false);
170  playlist_button.signal_clicked.connect (sigc::mem_fun(*this, &RouteTimeAxisView::playlist_click));
172 
173  if (is_track()) {
174 
175  if (ARDOUR::Profile->get_mixbus()) {
176  controls_table.attach (*rec_enable_button, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
177  } else {
178  controls_table.attach (*rec_enable_button, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
179  }
180 
181  if (is_midi_track()) {
182  ARDOUR_UI::instance()->set_tip(*rec_enable_button, _("Record (Right-click for Step Edit)"));
183  gm.set_fader_name ("MidiTrackFader");
184  } else {
186  gm.set_fader_name ("AudioTrackFader");
187  }
188 
189  rec_enable_button->set_sensitive (_session->writable());
190 
191  /* set playlist button tip to the current playlist, and make it update when it changes */
194 
195  } else {
196  gm.set_fader_name ("AudioBusFader");
197  Gtk::Fixed *blank = manage(new Gtk::Fixed());
198  controls_button_size_group->add_widget(*blank);
199  if (ARDOUR::Profile->get_mixbus() ) {
200  controls_table.attach (*blank, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
201  } else {
202  controls_table.attach (*blank, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
203  }
204  blank->show();
205  }
206 
207  top_hbox.pack_end(gm.get_level_meter(), false, false, 2);
208 
209  if (!ARDOUR::Profile->get_mixbus()) {
211  }
212 
213  _route->meter_change.connect (*this, invalidator (*this), bind (&RouteTimeAxisView::meter_changed, this), gui_context());
214  _route->input()->changed.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::io_changed, this, _1, _2), gui_context());
215  _route->output()->changed.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::io_changed, this, _1, _2), gui_context());
216  _route->track_number_changed.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::label_view, this), gui_context());
217 
218  if (ARDOUR::Profile->get_mixbus()) {
219  controls_table.attach (*mute_button, 1, 2, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
220  } else {
221  controls_table.attach (*mute_button, 3, 4, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
222  }
223  // mute button is always present, it is used to
224  // force the 'blank' placeholders to the proper size
226 
227  if (!_route->is_master()) {
228  if (ARDOUR::Profile->get_mixbus()) {
229  controls_table.attach (*solo_button, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
230  } else {
231  controls_table.attach (*solo_button, 4, 5, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
232  }
233  } else {
234  Gtk::Fixed *blank = manage(new Gtk::Fixed());
235  controls_button_size_group->add_widget(*blank);
236  if (ARDOUR::Profile->get_mixbus()) {
237  controls_table.attach (*blank, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
238  } else {
239  controls_table.attach (*blank, 4, 5, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
240  }
241  blank->show();
242  }
243 
244  if (ARDOUR::Profile->get_mixbus()) {
245  controls_table.attach (route_group_button, 2, 3, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
246  controls_table.attach (gm.get_gain_slider(), 3, 5, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 1, 0);
247  }
248  else if (!ARDOUR::Profile->get_trx()) {
249  controls_table.attach (route_group_button, 4, 5, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
250  controls_table.attach (gm.get_gain_slider(), 0, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 1, 0);
251  }
252 
255  ARDOUR_UI::instance()->set_tip(route_group_button, _("Route Group"));
256 
263 
264  if (is_midi_track()) {
265  ARDOUR_UI::instance()->set_tip(automation_button, _("MIDI Controllers and Automation"));
266  } else {
267  ARDOUR_UI::instance()->set_tip(automation_button, _("Automation"));
268  }
269 
271  label_view ();
272 
273  if (ARDOUR::Profile->get_mixbus()) {
274  controls_table.attach (automation_button, 1, 2, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
275  }
276  else if (!ARDOUR::Profile->get_trx()) {
277  controls_table.attach (automation_button, 3, 4, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
278  }
279 
280  if (is_track() && track()->mode() == ARDOUR::Normal) {
281  if (ARDOUR::Profile->get_mixbus()) {
282  controls_table.attach (playlist_button, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
283  }
284  else if (!ARDOUR::Profile->get_trx()) {
285  controls_table.attach (playlist_button, 2, 3, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
286  }
287  }
288 
289  _y_position = -1;
290 
291  _route->processors_changed.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::processors_changed, this, _1), gui_context());
292  _route->PropertyChanged.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::route_property_changed, this, _1), gui_context());
293 
294  if (is_track()) {
295 
296  str = gui_property ("layer-display");
297  if (!str.empty()) {
299  }
300 
301  track()->FreezeChange.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::map_frozen, this), gui_context());
302  track()->SpeedChanged.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::speed_changed, this), gui_context());
303 
304  /* pick up the correct freeze state */
305  map_frozen ();
306 
307  }
308 
309  _editor.ZoomChanged.connect (sigc::mem_fun(*this, &RouteTimeAxisView::reset_samples_per_pixel));
310  ColorsChanged.connect (sigc::mem_fun (*this, &RouteTimeAxisView::color_handler));
311 
312  PropertyList* plist = new PropertyList();
313 
314  plist->add (ARDOUR::Properties::mute, true);
315  plist->add (ARDOUR::Properties::solo, true);
316 
318 
319  gm.get_level_meter().signal_scroll_event().connect (sigc::mem_fun (*this, &RouteTimeAxisView::controls_ebox_scroll), false);
320 }
321 
323 {
325 
326  for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) {
327  delete *i;
328  }
329 
330  delete playlist_action_menu;
332 
333  delete _view;
334  _view = 0;
335 
336  _automation_tracks.clear ();
337 
338  delete route_group_menu;
339  CatchDeletion (this);
340 }
341 
342 void
344 {
345  /* map current state of the route */
346 
350 }
351 
355 void
357 {
358  _subplugin_menu_map.clear ();
359  subplugin_menu.items().clear ();
362 }
363 
364 gint
366 {
367  if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
368  if (_route->route_group()) {
370  }
371  return false;
372  }
373 
374  WeakRouteList r;
375  r.push_back (route ());
376 
377  route_group_menu->build (r);
378  route_group_menu->menu()->popup (ev->button, ev->time);
379 
380  return false;
381 }
382 
383 void
385 {
386  label_view ();
387 }
388 
389 void
391 {
392  string x = _route->name ();
393  if (x != name_label.get_text ()) {
394  name_label.set_text (x);
395  }
396  const int64_t track_number = _route->track_number ();
397  if (track_number == 0) {
398  number_label.set_text ("");
399  } else {
400  number_label.set_text (PBD::to_string (abs(_route->track_number ()), std::dec));
401  }
402 }
403 
404 void
406 {
407  DisplaySuspender ds;
408  bool show_label = _session->config.get_track_name_number();
409 
410  if (_route && _route->is_master()) {
411  show_label = false;
412  }
413 
414  if (number_label.get_parent()) {
415  controls_table.remove (number_label);
416  }
417  if (show_label) {
418  if (ARDOUR::Profile->get_mixbus()) {
419  controls_table.attach (number_label, 3, 4, 0, 1, Gtk::SHRINK, Gtk::EXPAND|Gtk::FILL, 1, 0);
420  } else {
421  controls_table.attach (number_label, 0, 1, 0, 1, Gtk::SHRINK, Gtk::EXPAND|Gtk::FILL, 1, 0);
422  }
423  // see ArdourButton::on_size_request(), we should probably use a global size-group here instead.
424  // except the width of the number label is subtracted from the name-hbox, so we
425  // need to explictly calculate it anyway until the name-label & entry become ArdourWidgets.
426  int tnw = (2 + std::max(2u, _session->track_number_decimals())) * number_label.char_pixel_width();
427  if (tnw & 1) --tnw;
428  number_label.set_size_request(tnw, -1);
429  number_label.show ();
430  name_hbox.set_size_request(TimeAxisView::name_width_px - 2 - tnw, -1); // -2 = cellspacing
431  } else {
432  number_label.hide ();
433  name_hbox.set_size_request(TimeAxisView::name_width_px, -1);
434  }
435 }
436 
437 void
439 {
440  if (p == "track-name-number") {
442  }
443 }
444 
445 void
447 {
448  if (what_changed.contains (ARDOUR::Properties::name)) {
449  label_view ();
450  }
451 }
452 
453 void
455 {
456  if (src != this) {
457  label_view ();
458  }
459 }
460 
461 void
463 {
466  playlist_action_menu->popup (1, gtk_get_current_event_time());
467 }
468 
469 void
471 {
474  automation_action_menu->popup (1, gtk_get_current_event_time());
475 }
476 
477 void
479 {
480  using namespace Menu_Helpers;
481 
482  /* detach subplugin_menu from automation_action_menu before we delete automation_action_menu,
483  otherwise bad things happen (see comment for similar case in MidiTimeAxisView::build_automation_action_menu)
484  */
485 
487 
488  _main_automation_menu_map.clear ();
489  delete automation_action_menu;
490  automation_action_menu = new Menu;
491 
492  MenuList& items = automation_action_menu->items();
493 
494  automation_action_menu->set_name ("ArdourContextMenu");
495 
496  items.push_back (MenuElem (_("Show All Automation"),
497  sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::show_all_automation), for_selection)));
498 
499  items.push_back (MenuElem (_("Show Existing Automation"),
500  sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::show_existing_automation), for_selection)));
501 
502  items.push_back (MenuElem (_("Hide All Automation"),
503  sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::hide_all_automation), for_selection)));
504 
505  /* Attach the plugin submenu. It may have previously been used elsewhere,
506  so it was detached above
507  */
508 
509  if (!subplugin_menu.items().empty()) {
510  items.push_back (SeparatorElem ());
511  items.push_back (MenuElem (_("Processor automation"), subplugin_menu));
512  items.back().set_sensitive (!for_selection || _editor.get_selection().tracks.size() == 1);;
513  }
514 
515  /* Add any route automation */
516 
517  if (gain_track) {
518  items.push_back (CheckMenuElem (_("Fader"), sigc::mem_fun (*this, &RouteTimeAxisView::update_gain_track_visibility)));
519  gain_automation_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
520  gain_automation_item->set_active ((!for_selection || _editor.get_selection().tracks.size() == 1) &&
522 
524  }
525 
526  if (trim_track) {
527  items.push_back (CheckMenuElem (_("Trim"), sigc::mem_fun (*this, &RouteTimeAxisView::update_trim_track_visibility)));
528  trim_automation_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
529  trim_automation_item->set_active ((!for_selection || _editor.get_selection().tracks.size() == 1) &&
531 
533  }
534 
535  if (mute_track) {
536  items.push_back (CheckMenuElem (_("Mute"), sigc::mem_fun (*this, &RouteTimeAxisView::update_mute_track_visibility)));
537  mute_automation_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
538  mute_automation_item->set_active ((!for_selection || _editor.get_selection().tracks.size() == 1) &&
540 
542  }
543 
544  if (!pan_tracks.empty()) {
545  items.push_back (CheckMenuElem (_("Pan"), sigc::mem_fun (*this, &RouteTimeAxisView::update_pan_track_visibility)));
546  pan_automation_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
547  pan_automation_item->set_active ((!for_selection || _editor.get_selection().tracks.size() == 1) &&
548  (!pan_tracks.empty() && string_is_affirmative (pan_tracks.front()->gui_property ("visible"))));
549 
550  set<Evoral::Parameter> const & params = _route->pannable()->what_can_be_automated ();
551  for (set<Evoral::Parameter>::const_iterator p = params.begin(); p != params.end(); ++p) {
553  }
554  }
555 }
556 
557 void
559 {
560  using namespace Menu_Helpers;
561 
562  /* prepare it */
563 
565 
566  /* now fill it with our stuff */
567 
568  MenuList& items = display_menu->items();
569  display_menu->set_name ("ArdourContextMenu");
570 
571  items.push_back (MenuElem (_("Color..."), sigc::mem_fun (*this, &RouteUI::choose_color)));
572 
573  items.push_back (MenuElem (_("Comments..."), sigc::mem_fun (*this, &RouteUI::open_comment_editor)));
574 
575  items.push_back (MenuElem (_("Inputs..."), sigc::mem_fun (*this, &RouteUI::edit_input_configuration)));
576 
577  items.push_back (MenuElem (_("Outputs..."), sigc::mem_fun (*this, &RouteUI::edit_output_configuration)));
578 
579  items.push_back (SeparatorElem());
580 
581  if (_size_menu) {
583  }
584  build_size_menu ();
585  items.push_back (MenuElem (_("Height"), *_size_menu));
586 
587  items.push_back (SeparatorElem());
588 
589  if (!Profile->get_sae()) {
590  items.push_back (MenuElem (_("Remote Control ID..."), sigc::mem_fun (*this, &RouteUI::open_remote_control_id_dialog)));
591  items.back().set_sensitive (_editor.get_selection().tracks.size() <= 1);
592  items.push_back (SeparatorElem());
593  }
594 
595  // Hook for derived classes to add type specific stuff
597 
598  if (is_track()) {
599 
600  Menu* layers_menu = manage (new Menu);
601  MenuList &layers_items = layers_menu->items();
602  layers_menu->set_name("ArdourContextMenu");
603 
604  RadioMenuItem::Group layers_group;
605 
606  /* Find out how many overlaid/stacked tracks we have in the selection */
607 
608  int overlaid = 0;
609  int stacked = 0;
611  for (TrackSelection::const_iterator i = s.begin(); i != s.end(); ++i) {
612  StreamView* v = (*i)->view ();
613  if (!v) {
614  continue;
615  }
616 
617  switch (v->layer_display ()) {
618  case Overlaid:
619  ++overlaid;
620  break;
621  case Stacked:
622  case Expanded:
623  ++stacked;
624  break;
625  }
626  }
627 
628  /* We're not connecting to signal_toggled() here; in the case where these two items are
629  set to be in the `inconsistent' state, it seems that one or other will end up active
630  as well as inconsistent (presumably due to the RadioMenuItem::Group). Then when you
631  select the active one, no toggled signal is emitted so nothing happens.
632  */
633 
635 
636  layers_items.push_back (RadioMenuElem (layers_group, _("Overlaid")));
637  RadioMenuItem* i = dynamic_cast<RadioMenuItem*> (&layers_items.back ());
638  i->set_active (overlaid != 0 && stacked == 0);
639  i->set_inconsistent (overlaid != 0 && stacked != 0);
640  i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_layer_display), Overlaid, true));
641 
642  layers_items.push_back (RadioMenuElem (layers_group, _("Stacked")));
643  i = dynamic_cast<RadioMenuItem*> (&layers_items.back ());
644  i->set_active (overlaid == 0 && stacked != 0);
645  i->set_inconsistent (overlaid != 0 && stacked != 0);
646  i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_layer_display), Stacked, true));
647 
649 
650  items.push_back (MenuElem (_("Layers"), *layers_menu));
651 
652  if (!Profile->get_sae()) {
653 
654  Menu* alignment_menu = manage (new Menu);
655  MenuList& alignment_items = alignment_menu->items();
656  alignment_menu->set_name ("ArdourContextMenu");
657 
658  RadioMenuItem::Group align_group;
659 
660  /* Same verbose hacks as for the layering options above */
661 
662  int existing = 0;
663  int capture = 0;
664  int automatic = 0;
665  int styles = 0;
666  boost::shared_ptr<Track> first_track;
667 
669  for (TrackSelection::const_iterator i = s.begin(); i != s.end(); ++i) {
670  RouteTimeAxisView* r = dynamic_cast<RouteTimeAxisView*> (*i);
671  if (!r || !r->is_track ()) {
672  continue;
673  }
674 
675  if (!first_track) {
676  first_track = r->track();
677  }
678 
679  switch (r->track()->alignment_choice()) {
680  case Automatic:
681  ++automatic;
682  styles |= 0x1;
683  switch (r->track()->alignment_style()) {
684  case ExistingMaterial:
685  ++existing;
686  break;
687  case CaptureTime:
688  ++capture;
689  break;
690  }
691  break;
692  case UseExistingMaterial:
693  ++existing;
694  styles |= 0x2;
695  break;
696  case UseCaptureTime:
697  ++capture;
698  styles |= 0x4;
699  break;
700  }
701  }
702 
703  bool inconsistent;
704  switch (styles) {
705  case 1:
706  case 2:
707  case 4:
708  inconsistent = false;
709  break;
710  default:
711  inconsistent = true;
712  break;
713  }
714 
715  RadioMenuItem* i;
716 
717  if (!inconsistent && first_track) {
718 
719  alignment_items.push_back (RadioMenuElem (align_group, _("Automatic (based on I/O connections)")));
720  i = dynamic_cast<RadioMenuItem*> (&alignment_items.back());
721  i->set_active (automatic != 0 && existing == 0 && capture == 0);
722  i->signal_activate().connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::set_align_choice), i, Automatic, true));
723 
724  switch (first_track->alignment_choice()) {
725  case Automatic:
726  switch (first_track->alignment_style()) {
727  case ExistingMaterial:
728  alignment_items.push_back (MenuElem (_("(Currently: Existing Material)")));
729  break;
730  case CaptureTime:
731  alignment_items.push_back (MenuElem (_("(Currently: Capture Time)")));
732  break;
733  }
734  break;
735  default:
736  break;
737  }
738 
739  alignment_items.push_back (RadioMenuElem (align_group, _("Align With Existing Material")));
740  i = dynamic_cast<RadioMenuItem*> (&alignment_items.back());
741  i->set_active (existing != 0 && capture == 0 && automatic == 0);
742  i->signal_activate().connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::set_align_choice), i, UseExistingMaterial, true));
743 
744  alignment_items.push_back (RadioMenuElem (align_group, _("Align With Capture Time")));
745  i = dynamic_cast<RadioMenuItem*> (&alignment_items.back());
746  i->set_active (existing == 0 && capture != 0 && automatic == 0);
747  i->signal_activate().connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::set_align_choice), i, UseCaptureTime, true));
748 
749  items.push_back (MenuElem (_("Alignment"), *alignment_menu));
750 
751  } else {
752  /* show nothing */
753  }
754 
755  Menu* mode_menu = manage (new Menu);
756  MenuList& mode_items = mode_menu->items ();
757  mode_menu->set_name ("ArdourContextMenu");
758 
759  RadioMenuItem::Group mode_group;
760 
761  int normal = 0;
762  int tape = 0;
763  int non_layered = 0;
764 
765  for (TrackSelection::const_iterator i = s.begin(); i != s.end(); ++i) {
766  RouteTimeAxisView* r = dynamic_cast<RouteTimeAxisView*> (*i);
767  if (!r || !r->is_track ()) {
768  continue;
769  }
770 
771  switch (r->track()->mode()) {
772  case Normal:
773  ++normal;
774  break;
775  case Destructive:
776  ++tape;
777  break;
778  case NonLayered:
779  ++non_layered;
780  break;
781  }
782  }
783 
784  mode_items.push_back (RadioMenuElem (mode_group, _("Normal Mode")));
785  i = dynamic_cast<RadioMenuItem*> (&mode_items.back ());
786  i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Normal, true));
787  i->set_active (normal != 0 && tape == 0 && non_layered == 0);
788  i->set_inconsistent (normal != 0 && (tape != 0 || non_layered != 0));
789 
790  mode_items.push_back (RadioMenuElem (mode_group, _("Tape Mode")));
791  i = dynamic_cast<RadioMenuItem*> (&mode_items.back ());
792  i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Destructive, true));
793  i->set_active (normal == 0 && tape != 0 && non_layered == 0);
794  i->set_inconsistent (tape != 0 && (normal != 0 || non_layered != 0));
795 
796  mode_items.push_back (RadioMenuElem (mode_group, _("Non-Layered Mode")));
797  i = dynamic_cast<RadioMenuItem*> (&mode_items.back ());
798  i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::NonLayered, true));
799  i->set_active (normal == 0 && tape == 0 && non_layered != 0);
800  i->set_inconsistent (non_layered != 0 && (normal != 0 || tape != 0));
801 
802  items.push_back (MenuElem (_("Record Mode"), *mode_menu));
803  }
804 
805 
806  items.push_back (SeparatorElem());
807 
809  items.push_back (MenuElem (_("Playlist"), *playlist_action_menu));
810  items.back().set_sensitive (_editor.get_selection().tracks.size() <= 1);
811  }
812 
814 
815  WeakRouteList r;
816  for (TrackSelection::iterator i = _editor.get_selection().tracks.begin(); i != _editor.get_selection().tracks.end(); ++i) {
817  RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
818  if (rtv) {
819  r.push_back (rtv->route ());
820  }
821  }
822 
823  if (r.empty ()) {
824  r.push_back (route ());
825  }
826 
827  route_group_menu->build (r);
828  items.push_back (MenuElem (_("Group"), *route_group_menu->menu ()));
829 
831  items.push_back (MenuElem (_("Automation"), *automation_action_menu));
832 
833  items.push_back (SeparatorElem());
834 
835  int active = 0;
836  int inactive = 0;
838  for (TrackSelection::const_iterator i = s.begin(); i != s.end(); ++i) {
839  RouteTimeAxisView* r = dynamic_cast<RouteTimeAxisView*> (*i);
840  if (!r) {
841  continue;
842  }
843 
844  if (r->route()->active()) {
845  ++active;
846  } else {
847  ++inactive;
848  }
849  }
850 
851  items.push_back (CheckMenuElem (_("Active")));
852  Gtk::CheckMenuItem* i = dynamic_cast<Gtk::CheckMenuItem *> (&items.back());
853  bool click_sets_active = true;
854  if (active > 0 && inactive == 0) {
855  i->set_active (true);
856  click_sets_active = false;
857  } else if (active > 0 && inactive > 0) {
858  i->set_inconsistent (true);
859  }
860  i->set_sensitive(! _session->transport_rolling());
861  i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::set_route_active), click_sets_active, true));
862 
863  items.push_back (SeparatorElem());
864  items.push_back (MenuElem (_("Hide"), sigc::bind (sigc::mem_fun(_editor, &PublicEditor::hide_track_in_display), this, true)));
865  items.push_front (SeparatorElem());
866  items.push_front (MenuElem (_("Remove"), sigc::mem_fun(_editor, &PublicEditor::remove_tracks)));
867 }
868 
869 void
870 RouteTimeAxisView::set_track_mode (TrackMode mode, bool apply_to_selection)
871 {
872  if (apply_to_selection) {
874  } else {
875 
876  bool needs_bounce = false;
877 
878  if (!track()->can_use_mode (mode, needs_bounce)) {
879 
880  if (!needs_bounce) {
881  /* cannot be done */
882  return;
883  } else {
884  cerr << "would bounce this one\n";
885  return;
886  }
887  }
888 
889  track()->set_mode (mode);
890  }
891 }
892 
893 void
895 {
896  TimeAxisView::show_timestretch (start, end, layers, layer);
897 
898  hide_timestretch ();
899 
900 #if 0
901  if (ts.empty()) {
902  return;
903  }
904 
905 
906  /* check that the time selection was made in our route, or our route group.
907  remember that route_group() == 0 implies the route is *not* in a edit group.
908  */
909 
910  if (!(ts.track == this || (ts.group != 0 && ts.group == _route->route_group()))) {
911  /* this doesn't apply to us */
912  return;
913  }
914 
915  /* ignore it if our edit group is not active */
916 
917  if ((ts.track != this) && _route->route_group() && !_route->route_group()->is_active()) {
918  return;
919  }
920 #endif
921 
922  if (timestretch_rect == 0) {
923  timestretch_rect = new ArdourCanvas::Rectangle (canvas_display ());
924  timestretch_rect->set_fill_color (ArdourCanvas::HSV (ARDOUR_UI::config()->color ("time stretch fill")).mod (ARDOUR_UI::config()->modifier ("time stretch fill")).color());
925  timestretch_rect->set_outline_color (ARDOUR_UI::config()->color ("time stretch outline"));
926  }
927 
928  timestretch_rect->show ();
929  timestretch_rect->raise_to_top ();
930 
931  double const x1 = start / _editor.get_current_zoom();
932  double const x2 = (end - 1) / _editor.get_current_zoom();
933 
934  timestretch_rect->set (ArdourCanvas::Rect (x1, current_height() * (layers - layer - 1) / layers,
935  x2, current_height() * (layers - layer) / layers));
936 }
937 
938 void
940 {
942 
943  if (timestretch_rect) {
944  timestretch_rect->hide ();
945  }
946 }
947 
948 void
950 {
951 
952 #if 0
953  /* ignore it if our edit group is not active or if the selection was started
954  in some other track or route group (remember that route_group() == 0 means
955  that the track is not in an route group).
956  */
957 
958  if (((ts.track != this && !is_child (ts.track)) && _route->route_group() && !_route->route_group()->is_active()) ||
959  (!(ts.track == this || is_child (ts.track) || (ts.group != 0 && ts.group == _route->route_group())))) {
960  hide_selection ();
961  return;
962  }
963 #endif
964 
966 }
967 
968 void
970 {
971  int gmlen = h - 9;
972  bool height_changed = (height == 0) || (h != height);
973 
974  int meter_width = 3;
975  if (_route && _route->shared_peak_meter()->input_streams().n_total() == 1) {
976  meter_width = 6;
977  }
978  gm.get_level_meter().setup_meters (gmlen, meter_width);
979 
981 
982  if (_view) {
983  _view->set_height ((double) current_height());
984  }
985 
986  if (height >= preset_height (HeightNormal)) {
987 
988  reset_meter();
989 
990  gm.get_gain_slider().show();
991  mute_button->show();
992  if (!_route || _route->is_monitor()) {
993  solo_button->hide();
994  } else {
995  solo_button->show();
996  }
997  if (rec_enable_button)
998  rec_enable_button->show();
999 
1000  route_group_button.show();
1001  automation_button.show();
1002 
1003  if (is_track() && track()->mode() == ARDOUR::Normal) {
1004  playlist_button.show();
1005  }
1006 
1007  } else {
1008 
1009  reset_meter();
1010 
1011  gm.get_gain_slider().hide();
1012  mute_button->show();
1013  if (!_route || _route->is_monitor()) {
1014  solo_button->hide();
1015  } else {
1016  solo_button->show();
1017  }
1018  if (rec_enable_button)
1019  rec_enable_button->show();
1020 
1021  route_group_button.hide ();
1022  automation_button.hide ();
1023 
1024  if (is_track() && track()->mode() == ARDOUR::Normal) {
1025  playlist_button.hide ();
1026  }
1027 
1028  }
1029 
1030  if (height_changed && !no_redraw) {
1031  /* only emit the signal if the height really changed */
1032  request_redraw ();
1033  }
1034 }
1035 
1036 void
1038 {
1039  if (_view) {
1041  }
1042 
1044 }
1045 
1046 void
1048 {
1050 }
1051 
1052 void
1054 {
1055  double speed = 1.0;
1056 
1057  if (track()) {
1058  speed = track()->speed();
1059  }
1060 
1061  if (_view) {
1062  _view->set_samples_per_pixel (fpp * speed);
1063  }
1064 
1066 }
1067 
1068 void
1069 RouteTimeAxisView::set_align_choice (RadioMenuItem* mitem, AlignChoice choice, bool apply_to_selection)
1070 {
1071  if (!mitem->get_active()) {
1072  /* this is one of the two calls made when these radio menu items change status. this one
1073  is for the item that became inactive, and we want to ignore it.
1074  */
1075  return;
1076  }
1077 
1078  if (apply_to_selection) {
1079  _editor.get_selection().tracks.foreach_route_time_axis (boost::bind (&RouteTimeAxisView::set_align_choice, _1, mitem, choice, false));
1080  } else {
1081  if (track ()) {
1082  track()->set_align_choice (choice);
1083  }
1084  }
1085 }
1086 
1087 void
1089 {
1090  ArdourPrompter prompter (true);
1091  string name;
1092 
1094  if (!tr || tr->destructive()) {
1095  return;
1096  }
1097 
1099  if (!pl) {
1100  return;
1101  }
1102 
1103  prompter.set_title (_("Rename Playlist"));
1104  prompter.set_prompt (_("New name for playlist:"));
1105  prompter.set_initial_text (pl->name());
1106  prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1107  prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1108 
1109  switch (prompter.run ()) {
1110  case Gtk::RESPONSE_ACCEPT:
1111  prompter.get_result (name);
1112  if (name.length()) {
1113  pl->set_name (name);
1114  }
1115  break;
1116 
1117  default:
1118  break;
1119  }
1120 }
1121 
1122 std::string
1124 {
1125  std::string ret (basename);
1126 
1127  std::string const group_string = "." + route_group()->name() + ".";
1128 
1129  // iterate through all playlists
1130  int maxnumber = 0;
1131  for (vector<boost::shared_ptr<Playlist> >::const_iterator i = playlists.begin(); i != playlists.end(); ++i) {
1132  std::string tmp = (*i)->name();
1133 
1134  std::string::size_type idx = tmp.find(group_string);
1135  // find those which belong to this group
1136  if (idx != string::npos) {
1137  tmp = tmp.substr(idx + group_string.length());
1138 
1139  // and find the largest current number
1140  int x = atoi(tmp);
1141  if (x > maxnumber) {
1142  maxnumber = x;
1143  }
1144  }
1145  }
1146 
1147  maxnumber++;
1148 
1149  char buf[32];
1150  snprintf (buf, sizeof(buf), "%d", maxnumber);
1151 
1152  ret = this->name() + "." + route_group()->name () + "." + buf;
1153 
1154  return ret;
1155 }
1156 
1157 void
1158 RouteTimeAxisView::use_copy_playlist (bool prompt, vector<boost::shared_ptr<Playlist> > const & playlists_before_op)
1159 {
1160  string name;
1161 
1163  if (!tr || tr->destructive()) {
1164  return;
1165  }
1166 
1168  if (!pl) {
1169  return;
1170  }
1171 
1172  name = pl->name();
1173 
1174  if (route_group() && route_group()->is_active() && route_group()->enabled_property (ARDOUR::Properties::select.property_id)) {
1175  name = resolve_new_group_playlist_name(name, playlists_before_op);
1176  }
1177 
1178  while (_session->playlists->by_name(name)) {
1179  name = Playlist::bump_name (name, *_session);
1180  }
1181 
1182  // TODO: The prompter "new" button should be de-activated if the user
1183  // specifies a playlist name which already exists in the session.
1184 
1185  if (prompt) {
1186 
1187  ArdourPrompter prompter (true);
1188 
1189  prompter.set_title (_("New Copy Playlist"));
1190  prompter.set_prompt (_("Name for new playlist:"));
1191  prompter.set_initial_text (name);
1192  prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT);
1193  prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, true);
1194  prompter.show_all ();
1195 
1196  switch (prompter.run ()) {
1197  case Gtk::RESPONSE_ACCEPT:
1198  prompter.get_result (name);
1199  break;
1200 
1201  default:
1202  return;
1203  }
1204  }
1205 
1206  if (name.length()) {
1207  tr->use_copy_playlist ();
1208  tr->playlist()->set_name (name);
1209  }
1210 }
1211 
1212 void
1213 RouteTimeAxisView::use_new_playlist (bool prompt, vector<boost::shared_ptr<Playlist> > const & playlists_before_op)
1214 {
1215  string name;
1216 
1218  if (!tr || tr->destructive()) {
1219  return;
1220  }
1221 
1223  if (!pl) {
1224  return;
1225  }
1226 
1227  name = pl->name();
1228 
1229  if (route_group() && route_group()->is_active() && route_group()->enabled_property (ARDOUR::Properties::select.property_id)) {
1230  name = resolve_new_group_playlist_name(name,playlists_before_op);
1231  }
1232 
1233  while (_session->playlists->by_name(name)) {
1234  name = Playlist::bump_name (name, *_session);
1235  }
1236 
1237 
1238  if (prompt) {
1239 
1240  ArdourPrompter prompter (true);
1241 
1242  prompter.set_title (_("New Playlist"));
1243  prompter.set_prompt (_("Name for new playlist:"));
1244  prompter.set_initial_text (name);
1245  prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT);
1246  prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, true);
1247 
1248  switch (prompter.run ()) {
1249  case Gtk::RESPONSE_ACCEPT:
1250  prompter.get_result (name);
1251  break;
1252 
1253  default:
1254  return;
1255  }
1256  }
1257 
1258  if (name.length()) {
1259  tr->use_new_playlist ();
1260  tr->playlist()->set_name (name);
1261  }
1262 }
1263 
1264 void
1266 {
1268  if (!tr || tr->destructive()) {
1269  return;
1270  }
1271 
1273  if (!pl) {
1274  return;
1275  }
1276 
1277  _editor.clear_playlist (pl);
1278 }
1279 
1280 void
1282 {
1284 }
1285 
1286 void
1288 {
1289  if (!track()) {
1290  return;
1291  }
1292 
1293  map_frozen ();
1294 }
1295 
1296 void
1298 {
1299  if (Keyboard::modifier_state_equals (ev->state, (Keyboard::TertiaryModifier|Keyboard::PrimaryModifier))) {
1300 
1301  /* special case: select/deselect all tracks */
1302 
1303  _editor.begin_reversible_selection_op (X_("Selection Click"));
1304 
1305  if (_editor.get_selection().selected (this)) {
1307  } else {
1309  }
1310 
1312 
1313  return;
1314  }
1315 
1316  _editor.begin_reversible_selection_op (X_("Selection Click"));
1317 
1318  switch (ArdourKeyboard::selection_type (ev->state)) {
1319  case Selection::Toggle:
1320  _editor.get_selection().toggle (this);
1321  break;
1322 
1323  case Selection::Set:
1324  _editor.get_selection().set (this);
1325  break;
1326 
1327  case Selection::Extend:
1329  break;
1330 
1331  case Selection::Add:
1332  _editor.get_selection().add (this);
1333  break;
1334  }
1335 
1337 }
1338 
1339 void
1341 {
1342  for (Children::iterator i = children.begin(); i != children.end(); ++i) {
1343  (*i)->set_selected_points (points);
1344  }
1345 }
1346 
1347 void
1349 {
1350  if (_view) {
1351  _view->set_selected_regionviews (regions);
1352  }
1353 }
1354 
1358 void
1359 RouteTimeAxisView::get_selectables (framepos_t start, framepos_t end, double top, double bot, list<Selectable*>& results, bool within)
1360 {
1361  double speed = 1.0;
1362 
1363  if (track() != 0) {
1364  speed = track()->speed();
1365  }
1366 
1367  framepos_t const start_adjusted = session_frame_to_track_frame(start, speed);
1368  framepos_t const end_adjusted = session_frame_to_track_frame(end, speed);
1369 
1370  if ((_view && ((top < 0.0 && bot < 0.0))) || touched (top, bot)) {
1371  _view->get_selectables (start_adjusted, end_adjusted, top, bot, results, within);
1372  }
1373 
1374  /* pick up visible automation tracks */
1375 
1376  for (Children::iterator i = children.begin(); i != children.end(); ++i) {
1377  if (!(*i)->hidden()) {
1378  (*i)->get_selectables (start_adjusted, end_adjusted, top, bot, results, within);
1379  }
1380  }
1381 }
1382 
1383 void
1384 RouteTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& results)
1385 {
1386  if (_view) {
1387  _view->get_inverted_selectables (sel, results);
1388  }
1389 
1390  for (Children::iterator i = children.begin(); i != children.end(); ++i) {
1391  if (!(*i)->hidden()) {
1392  (*i)->get_inverted_selectables (sel, results);
1393  }
1394  }
1395 
1396  return;
1397 }
1398 
1399 RouteGroup*
1401 {
1402  return _route->route_group();
1403 }
1404 
1405 string
1407 {
1408  return _route->name();
1409 }
1410 
1413 {
1415 
1416  if ((tr = track()) != 0) {
1417  return tr->playlist();
1418  } else {
1419  return boost::shared_ptr<Playlist> ();
1420  }
1421 }
1422 
1423 void
1425 {
1427 
1428  string x = name_entry->get_text ();
1429 
1430  if (x == _route->name()) {
1431  return;
1432  }
1433 
1435 
1436  if (x.length() == 0) {
1437  name_entry->set_text (_route->name());
1438  return;
1439  }
1440 
1441  if (_session->route_name_internal (x)) {
1442  ARDOUR_UI::instance()->popup_error (string_compose (_("You cannot create a track with that name as it is reserved for %1"),
1443  PROGRAM_NAME));
1444  name_entry->grab_focus ();
1445  } else if (RouteUI::verify_new_route_name (x)) {
1446  _route->set_name (x);
1447  } else {
1448  name_entry->grab_focus ();
1449  }
1450 }
1451 
1454 {
1456 
1457  if (pl) {
1458  return pl->find_next_region (pos, point, dir);
1459  }
1460 
1461  return boost::shared_ptr<Region> ();
1462 }
1463 
1464 framepos_t
1466 {
1468 
1469  if (pl) {
1470  return pl->find_next_region_boundary (pos, dir);
1471  }
1472 
1473  return -1;
1474 }
1475 
1476 void
1478 {
1479  boost::shared_ptr<Playlist> what_we_got;
1482 
1483  if (tr == 0) {
1484  /* route is a bus, not a track */
1485  return;
1486  }
1487 
1488  playlist = tr->playlist();
1489 
1490  TimeSelection time (selection);
1491  float const speed = tr->speed();
1492  if (speed != 1.0f) {
1493  for (TimeSelection::iterator i = time.begin(); i != time.end(); ++i) {
1494  (*i).start = session_frame_to_track_frame((*i).start, speed);
1495  (*i).end = session_frame_to_track_frame((*i).end, speed);
1496  }
1497  }
1498 
1499  playlist->clear_changes ();
1500  playlist->clear_owned_changes ();
1501 
1502  playlist->fade_range (time);
1503 
1504  vector<Command*> cmds;
1505  playlist->rdiff (cmds);
1506  _session->add_commands (cmds);
1507  _session->add_command (new StatefulDiffCommand (playlist));
1508 
1509 }
1510 
1511 void
1513 {
1514  boost::shared_ptr<Playlist> what_we_got;
1517 
1518  if (tr == 0) {
1519  /* route is a bus, not a track */
1520  return;
1521  }
1522 
1523  playlist = tr->playlist();
1524 
1525  TimeSelection time (selection.time);
1526  float const speed = tr->speed();
1527  if (speed != 1.0f) {
1528  for (TimeSelection::iterator i = time.begin(); i != time.end(); ++i) {
1529  (*i).start = session_frame_to_track_frame((*i).start, speed);
1530  (*i).end = session_frame_to_track_frame((*i).end, speed);
1531  }
1532  }
1533 
1534  playlist->clear_changes ();
1535  playlist->clear_owned_changes ();
1536 
1537  switch (op) {
1538  case Delete:
1539  if (playlist->cut (time) != 0) {
1540  if (Config->get_edit_mode() == Ripple)
1541  playlist->ripple(time.start(), -time.length(), NULL);
1542  // no need to exclude any regions from rippling here
1543 
1544  vector<Command*> cmds;
1545  playlist->rdiff (cmds);
1546  _session->add_commands (cmds);
1547 
1548  _session->add_command (new StatefulDiffCommand (playlist));
1549  }
1550  break;
1551 
1552  case Cut:
1553  if ((what_we_got = playlist->cut (time)) != 0) {
1554  _editor.get_cut_buffer().add (what_we_got);
1555  if (Config->get_edit_mode() == Ripple)
1556  playlist->ripple(time.start(), -time.length(), NULL);
1557  // no need to exclude any regions from rippling here
1558 
1559  vector<Command*> cmds;
1560  playlist->rdiff (cmds);
1561  _session->add_commands (cmds);
1562 
1563  _session->add_command (new StatefulDiffCommand (playlist));
1564  }
1565  break;
1566  case Copy:
1567  if ((what_we_got = playlist->copy (time)) != 0) {
1568  _editor.get_cut_buffer().add (what_we_got);
1569  }
1570  break;
1571 
1572  case Clear:
1573  if ((what_we_got = playlist->cut (time)) != 0) {
1574  if (Config->get_edit_mode() == Ripple)
1575  playlist->ripple(time.start(), -time.length(), NULL);
1576  // no need to exclude any regions from rippling here
1577 
1578  vector<Command*> cmds;
1579  playlist->rdiff (cmds);
1580  _session->add_commands (cmds);
1581  _session->add_command (new StatefulDiffCommand (playlist));
1582  what_we_got->release ();
1583  }
1584  break;
1585  }
1586 }
1587 
1588 bool
1590 {
1591  if (!is_track()) {
1592  return false;
1593  }
1594 
1596  const ARDOUR::DataType type = pl->data_type();
1597  PlaylistSelection::const_iterator p = selection.playlists.get_nth(type, ctx.counts.n_playlists(type));
1598 
1599  if (p == selection.playlists.end()) {
1600  return false;
1601  }
1602  ctx.counts.increase_n_playlists(type);
1603 
1604  DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("paste to %1\n", pos));
1605 
1606  if (track()->speed() != 1.0f) {
1607  pos = session_frame_to_track_frame (pos, track()->speed());
1608  DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("modified paste to %1\n", pos));
1609  }
1610 
1611  /* add multi-paste offset if applicable */
1612  std::pair<framepos_t, framepos_t> extent = (*p)->get_extent();
1613  const framecnt_t duration = extent.second - extent.first;
1614  pos += _editor.get_paste_offset(pos, ctx.count, duration);
1615 
1616  pl->clear_changes ();
1617  if (Config->get_edit_mode() == Ripple) {
1618  std::pair<framepos_t, framepos_t> extent = (*p)->get_extent_with_endspace();
1619  framecnt_t amount = extent.second - extent.first;
1620  pl->ripple(pos, amount * ctx.times, boost::shared_ptr<Region>());
1621  }
1622  pl->paste (*p, pos, ctx.times);
1623 
1624  vector<Command*> cmds;
1625  pl->rdiff (cmds);
1626  _session->add_commands (cmds);
1627 
1629 
1630  return true;
1631 }
1632 
1633 
1636  return a->sort_id() < b->sort_id();
1637  }
1638 };
1639 
1640 void
1642 {
1643  using namespace Menu_Helpers;
1644 
1645  if (!is_track()) {
1646  return;
1647  }
1648 
1649  delete playlist_action_menu;
1650  playlist_action_menu = new Menu;
1651  playlist_action_menu->set_name ("ArdourContextMenu");
1652 
1653  MenuList& playlist_items = playlist_action_menu->items();
1654  playlist_action_menu->set_name ("ArdourContextMenu");
1655  playlist_items.clear();
1656 
1657  RadioMenuItem::Group playlist_group;
1659 
1660  vector<boost::shared_ptr<Playlist> > playlists_tr = _session->playlists->playlists_for_track (tr);
1661 
1662  /* sort the playlists */
1663  PlaylistSorter cmp;
1664  sort (playlists_tr.begin(), playlists_tr.end(), cmp);
1665 
1666  /* add the playlists to the menu */
1667  for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists_tr.begin(); i != playlists_tr.end(); ++i) {
1668  playlist_items.push_back (RadioMenuElem (playlist_group, (*i)->name()));
1669  RadioMenuItem *item = static_cast<RadioMenuItem*>(&playlist_items.back());
1670  item->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::use_playlist), item, boost::weak_ptr<Playlist> (*i)));
1671 
1672  if (tr->playlist()->id() == (*i)->id()) {
1673  item->set_active();
1674 
1675  }
1676  }
1677 
1678  playlist_items.push_back (SeparatorElem());
1679  playlist_items.push_back (MenuElem (_("Rename..."), sigc::mem_fun(*this, &RouteTimeAxisView::rename_current_playlist)));
1680  playlist_items.push_back (SeparatorElem());
1681 
1682  if (!route_group() || !route_group()->is_active() || !route_group()->enabled_property (ARDOUR::Properties::select.property_id)) {
1683  playlist_items.push_back (MenuElem (_("New..."), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::new_playlists), this)));
1684  playlist_items.push_back (MenuElem (_("New Copy..."), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::copy_playlists), this)));
1685 
1686  } else {
1687  // Use a label which tells the user what is happening
1688  playlist_items.push_back (MenuElem (_("New Take"), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::new_playlists), this)));
1689  playlist_items.push_back (MenuElem (_("Copy Take"), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::copy_playlists), this)));
1690 
1691  }
1692 
1693  playlist_items.push_back (SeparatorElem());
1694  playlist_items.push_back (MenuElem (_("Clear Current"), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::clear_playlists), this)));
1695  playlist_items.push_back (SeparatorElem());
1696 
1697  playlist_items.push_back (MenuElem(_("Select From All..."), sigc::mem_fun(*this, &RouteTimeAxisView::show_playlist_selector)));
1698 }
1699 
1700 void
1702 {
1703  assert (is_track());
1704 
1705  // exit if we were triggered by deactivating the old playlist
1706  if (!item->get_active()) {
1707  return;
1708  }
1709 
1710  boost::shared_ptr<Playlist> pl (wpl.lock());
1711 
1712  if (!pl) {
1713  return;
1714  }
1715 
1716  if (track()->playlist() == pl) {
1717  // exit when use_playlist is called by the creation of the playlist menu
1718  // or the playlist choice is unchanged
1719  return;
1720  }
1721 
1722  track()->use_playlist (pl);
1723 
1724  RouteGroup* rg = route_group();
1725 
1726  if (rg && rg->is_active() && rg->enabled_property (ARDOUR::Properties::select.property_id)) {
1727  std::string group_string = "." + rg->name() + ".";
1728 
1729  std::string take_name = pl->name();
1730  std::string::size_type idx = take_name.find(group_string);
1731 
1732  if (idx == std::string::npos)
1733  return;
1734 
1735  take_name = take_name.substr(idx + group_string.length()); // find the bit containing the take number / name
1736 
1738 
1739  for (RouteList::const_iterator i = rl->begin(); i != rl->end(); ++i) {
1740  if ((*i) == this->route()) {
1741  continue;
1742  }
1743 
1744  std::string playlist_name = (*i)->name()+group_string+take_name;
1745 
1747  if (!track) {
1748  continue;
1749  }
1750 
1751  if (track->freeze_state() == Track::Frozen) {
1752  /* Don't change playlists of frozen tracks */
1753  continue;
1754  }
1755 
1756  boost::shared_ptr<Playlist> ipl = session()->playlists->by_name(playlist_name);
1757  if (!ipl) {
1758  // No playlist for this track for this take yet, make it
1759  track->use_new_playlist();
1760  track->playlist()->set_name(playlist_name);
1761  } else {
1762  track->use_playlist(ipl);
1763  }
1764  }
1765  }
1766 }
1767 
1768 void
1770 {
1771  RouteGroup* rg = route_group ();
1772  if (rg && rg->is_active() && rg->enabled_property (ARDOUR::Properties::select.property_id)) {
1773  string group_string = "." + rg->name() + ".";
1774 
1775  string take_name = track()->playlist()->name();
1776  string::size_type idx = take_name.find(group_string);
1777 
1778  if (idx != string::npos) {
1779  /* find the bit containing the take number / name */
1780  take_name = take_name.substr (idx + group_string.length());
1781 
1782  /* set the playlist button tooltip to the take name */
1785  string_compose(_("Take: %1.%2"),
1786  Glib::Markup::escape_text(rg->name()),
1787  Glib::Markup::escape_text(take_name))
1788  );
1789 
1790  return;
1791  }
1792  }
1793 
1794  /* set the playlist button tooltip to the playlist name */
1795  ARDOUR_UI::instance()->set_tip (playlist_button, _("Playlist") + std::string(": ") + Glib::Markup::escape_text(track()->playlist()->name()));
1796 }
1797 
1798 
1799 void
1801 {
1803 }
1804 
1805 void
1807 {
1808  if (!is_track()) {
1809  return;
1810  }
1811 
1813 
1814  switch (track()->freeze_state()) {
1815  case Track::Frozen:
1816  playlist_button.set_sensitive (false);
1817  rec_enable_button->set_sensitive (false);
1818  break;
1819  default:
1820  playlist_button.set_sensitive (true);
1821  rec_enable_button->set_sensitive (true);
1822  break;
1823  }
1824 }
1825 
1826 void
1828 {
1829  //case cTimeStretchOutline:
1830  if (timestretch_rect) {
1831  timestretch_rect->set_outline_color (ARDOUR_UI::config()->color ("time stretch outline"));
1832  }
1833  //case cTimeStretchFill:
1834  if (timestretch_rect) {
1835  timestretch_rect->set_fill_color (ARDOUR_UI::config()->color ("time stretch fill"));
1836  }
1837 
1838  reset_meter();
1839 }
1840 
1844 void
1846 {
1848  Gtk::CheckMenuItem* menu = automation_child_menu_item (param);
1849 
1850  if (!track) {
1851  /* it doesn't exist yet, so we don't care about the button state: just add it */
1852  create_automation_child (param, true);
1853  } else {
1854  assert (menu);
1855  bool yn = menu->get_active();
1856  bool changed = false;
1857 
1858  if ((changed = track->set_marked_for_display (menu->get_active())) && yn) {
1859 
1860  /* we made it visible, now trigger a redisplay. if it was hidden, then automation_track_hidden()
1861  will have done that for us.
1862  */
1863 
1864  if (changed && !no_redraw) {
1865  request_redraw ();
1866  }
1867  }
1868  }
1869 }
1870 
1871 void
1873 {
1875 
1876  if (!track) {
1877  return;
1878  }
1879 
1880  Gtk::CheckMenuItem* menu = automation_child_menu_item (param);
1881 
1882  if (menu && !_hidden) {
1883  ignore_toggle = true;
1884  menu->set_active (false);
1885  ignore_toggle = false;
1886  }
1887 
1888  if (_route && !no_redraw) {
1889  request_redraw ();
1890  }
1891 }
1892 
1893 void
1895 {
1896  bool const showit = gain_automation_item->get_active();
1897 
1898  if (showit != string_is_affirmative (gain_track->gui_property ("visible"))) {
1900 
1901  /* now trigger a redisplay */
1902 
1903  if (!no_redraw) {
1904  _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
1905  }
1906  }
1907 }
1908 
1909 void
1911 {
1912  bool const showit = trim_automation_item->get_active();
1913 
1914  if (showit != string_is_affirmative (trim_track->gui_property ("visible"))) {
1916 
1917  /* now trigger a redisplay */
1918 
1919  if (!no_redraw) {
1920  _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
1921  }
1922  }
1923 }
1924 
1925 void
1927 {
1928  bool const showit = mute_automation_item->get_active();
1929 
1930  if (showit != string_is_affirmative (mute_track->gui_property ("visible"))) {
1932 
1933  /* now trigger a redisplay */
1934 
1935  if (!no_redraw) {
1936  _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
1937  }
1938  }
1939 }
1940 
1941 void
1943 {
1944  bool const showit = pan_automation_item->get_active();
1945  bool changed = false;
1946 
1947  for (list<boost::shared_ptr<AutomationTimeAxisView> >::iterator i = pan_tracks.begin(); i != pan_tracks.end(); ++i) {
1948  if ((*i)->set_marked_for_display (showit)) {
1949  changed = true;
1950  }
1951  }
1952 
1953  if (changed) {
1954  _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
1955  }
1956 }
1957 
1958 void
1960 {
1961  bool changed = false;
1962  for (list<boost::shared_ptr<AutomationTimeAxisView> >::iterator i = pan_tracks.begin(); i != pan_tracks.end(); ++i) {
1963  changed = true;
1964  (*i)->set_marked_for_display (false);
1965  }
1966  if (changed) {
1967  _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
1968  }
1969  pan_tracks.clear();
1970 
1971  if (!_route->panner()) {
1972  return;
1973  }
1974 
1975  set<Evoral::Parameter> params = _route->panner()->what_can_be_automated();
1976  set<Evoral::Parameter>::iterator p;
1977 
1978  for (p = params.begin(); p != params.end(); ++p) {
1979  boost::shared_ptr<ARDOUR::AutomationControl> pan_control = _route->pannable()->automation_control(*p);
1980 
1981  if (pan_control->parameter().type() == NullAutomation) {
1982  error << "Pan control has NULL automation type!" << endmsg;
1983  continue;
1984  }
1985 
1986  if (automation_child (pan_control->parameter ()).get () == 0) {
1987 
1988  /* we don't already have an AutomationTimeAxisView for this parameter */
1989 
1990  std::string const name = _route->panner()->describe_parameter (pan_control->parameter ());
1991 
1994  _route,
1995  _route->pannable(),
1996  pan_control,
1997  pan_control->parameter (),
1998  _editor,
1999  *this,
2000  false,
2001  parent_canvas,
2002  name)
2003  );
2004 
2005  pan_tracks.push_back (t);
2006  add_automation_child (*p, t, show);
2007  } else {
2008  pan_tracks.push_back (automation_child (pan_control->parameter ()));
2009  }
2010  }
2011 }
2012 
2013 
2014 void
2016 {
2017  if (apply_to_selection) {
2019  } else {
2020  no_redraw = true;
2021 
2022  /* Show our automation */
2023 
2024  for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
2025  i->second->set_marked_for_display (true);
2026 
2027  Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first);
2028 
2029  if (menu) {
2030  menu->set_active(true);
2031  }
2032  }
2033 
2034 
2035  /* Show processor automation */
2036 
2037  for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) {
2038  for (vector<ProcessorAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
2039  if ((*ii)->view == 0) {
2040  add_processor_automation_curve ((*i)->processor, (*ii)->what);
2041  }
2042 
2043  (*ii)->menu_item->set_active (true);
2044  }
2045  }
2046 
2047  no_redraw = false;
2048 
2049  /* Redraw */
2050 
2051  request_redraw ();
2052  }
2053 }
2054 
2055 void
2057 {
2058  if (apply_to_selection) {
2060  } else {
2061  no_redraw = true;
2062 
2063  /* Show our automation */
2064 
2065  for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
2066  if (i->second->has_automation()) {
2067  i->second->set_marked_for_display (true);
2068 
2069  Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first);
2070  if (menu) {
2071  menu->set_active(true);
2072  }
2073  }
2074  }
2075 
2076  /* Show processor automation */
2077 
2078  for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) {
2079  for (vector<ProcessorAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
2080  if ((*ii)->view != 0 && (*i)->processor->control((*ii)->what)->list()->size() > 0) {
2081  (*ii)->menu_item->set_active (true);
2082  }
2083  }
2084  }
2085 
2086  no_redraw = false;
2087 
2088  request_redraw ();
2089  }
2090 }
2091 
2092 void
2094 {
2095  if (apply_to_selection) {
2097  } else {
2098  no_redraw = true;
2099 
2100  /* Hide our automation */
2101 
2102  for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
2103  i->second->set_marked_for_display (false);
2104 
2105  Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first);
2106 
2107  if (menu) {
2108  menu->set_active (false);
2109  }
2110  }
2111 
2112  /* Hide processor automation */
2113 
2114  for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) {
2115  for (vector<ProcessorAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
2116  (*ii)->menu_item->set_active (false);
2117  }
2118  }
2119 
2120  no_redraw = false;
2121  request_redraw ();
2122  }
2123 }
2124 
2125 
2126 void
2128 {
2129  /* XXX need to find out if automation children have automationstreamviews. If yes, no ghosts */
2130  for (Children::iterator i = children.begin(); i != children.end(); ++i) {
2132 
2133  if ((atv = boost::dynamic_pointer_cast<AutomationTimeAxisView> (*i)) != 0) {
2134  atv->add_ghost(rv);
2135  }
2136  }
2137 
2138  for (UnderlayMirrorList::iterator i = _underlay_mirrors.begin(); i != _underlay_mirrors.end(); ++i) {
2139  (*i)->add_ghost(rv);
2140  }
2141 }
2142 
2144 {
2145  for (vector<ProcessorAutomationNode*>::iterator i = lines.begin(); i != lines.end(); ++i) {
2146  delete *i;
2147  }
2148 }
2149 
2150 
2152 {
2153  parent.remove_processor_automation_node (this);
2154 }
2155 
2156 void
2158 {
2159  if (pan->view) {
2160  remove_child (pan->view);
2161  }
2162 }
2163 
2166 {
2167  for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) {
2168 
2169  if ((*i)->processor == processor) {
2170 
2171  for (vector<ProcessorAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
2172  if ((*ii)->what == what) {
2173  return *ii;
2174  }
2175  }
2176  }
2177  }
2178 
2179  return 0;
2180 }
2181 
2183 void
2185 {
2186  string name;
2188 
2189  if ((pan = find_processor_automation_node (processor, what)) == 0) {
2190  /* session state may never have been saved with new plugin */
2191  error << _("programming error: ")
2192  << string_compose (X_("processor automation curve for %1:%2/%3/%4 not registered with track!"),
2193  processor->name(), what.type(), (int) what.channel(), what.id() )
2194  << endmsg;
2195  abort(); /*NOTREACHED*/
2196  return;
2197  }
2198 
2199  if (pan->view) {
2200  return;
2201  }
2202 
2204  = boost::dynamic_pointer_cast<AutomationControl>(processor->control(what, true));
2205 
2207  new AutomationTimeAxisView (_session, _route, processor, control, control->parameter (),
2208  _editor, *this, false, parent_canvas,
2209  processor->describe_parameter (what), processor->name()));
2210 
2211  pan->view->Hiding.connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::processor_automation_track_hidden), pan, processor));
2212 
2213  add_automation_child (control->parameter(), pan->view, pan->view->marked_for_display ());
2214 
2215  if (_view) {
2216  _view->foreach_regionview (sigc::mem_fun(*pan->view.get(), &TimeAxisView::add_ghost));
2217  }
2218 }
2219 
2220 void
2222 {
2223  if (!_hidden) {
2224  pan->menu_item->set_active (false);
2225  }
2226 
2227  if (!no_redraw) {
2228  request_redraw ();
2229  }
2230 }
2231 
2232 void
2234 {
2235  boost::shared_ptr<Processor> processor (p.lock ());
2236 
2237  if (!processor || boost::dynamic_pointer_cast<Amp> (processor)) {
2238  /* The Amp processor is a special case and is dealt with separately */
2239  return;
2240  }
2241 
2242  set<Evoral::Parameter> existing;
2243 
2244  processor->what_has_data (existing);
2245 
2246  for (set<Evoral::Parameter>::iterator i = existing.begin(); i != existing.end(); ++i) {
2247 
2248  Evoral::Parameter param (*i);
2250 
2251  if ((al = find_processor_automation_curve (processor, param)) != 0) {
2252  al->queue_reset ();
2253  } else {
2254  add_processor_automation_curve (processor, param);
2255  }
2256  }
2257 }
2258 
2259 void
2261 {
2262  using namespace Menu_Helpers;
2263 
2264  add_child (track);
2265 
2266  track->Hiding.connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::automation_track_hidden), param));
2267 
2268  _automation_tracks[param] = track;
2269 
2270  /* existing state overrides "show" argument */
2271  string s = track->gui_property ("visible");
2272  if (!s.empty()) {
2273  show = string_is_affirmative (s);
2274  }
2275 
2276  /* this might or might not change the visibility status, so don't rely on it */
2277  track->set_marked_for_display (show);
2278 
2279  if (show && !no_redraw) {
2280  request_redraw ();
2281  }
2282 
2284  /* MIDI-related parameters are always in the menu, there's no
2285  reason to rebuild the menu just because we added a automation
2286  lane for one of them. But if we add a non-MIDI automation
2287  lane, then we need to invalidate the display menu.
2288  */
2289  delete display_menu;
2290  display_menu = 0;
2291  }
2292 }
2293 
2294 void
2296 {
2297  boost::shared_ptr<Processor> processor (p.lock ());
2298 
2299  if (!processor || !processor->display_to_user ()) {
2300  return;
2301  }
2302 
2303  /* we use this override to veto the Amp processor from the plugin menu,
2304  as its automation lane can be accessed using the special "Fader" menu
2305  option
2306  */
2307 
2308  if (boost::dynamic_pointer_cast<Amp> (processor) != 0) {
2309  return;
2310  }
2311 
2312  using namespace Menu_Helpers;
2314  list<ProcessorAutomationInfo*>::iterator x;
2315 
2316  const std::set<Evoral::Parameter>& automatable = processor->what_can_be_automated ();
2317 
2318  if (automatable.empty()) {
2319  return;
2320  }
2321 
2322  for (x = processor_automation.begin(); x != processor_automation.end(); ++x) {
2323  if ((*x)->processor == processor) {
2324  break;
2325  }
2326  }
2327 
2328  if (x == processor_automation.end()) {
2329 
2330  rai = new ProcessorAutomationInfo (processor);
2331  processor_automation.push_back (rai);
2332 
2333  } else {
2334 
2335  rai = *x;
2336 
2337  }
2338 
2339  /* any older menu was deleted at the top of processors_changed()
2340  when we cleared the subplugin menu.
2341  */
2342 
2343  rai->menu = manage (new Menu);
2344  MenuList& items = rai->menu->items();
2345  rai->menu->set_name ("ArdourContextMenu");
2346 
2347  items.clear ();
2348 
2349  std::set<Evoral::Parameter> has_visible_automation;
2350  AutomationTimeAxisView::what_has_visible_automation (processor, has_visible_automation);
2351 
2352  for (std::set<Evoral::Parameter>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) {
2353 
2355  Gtk::CheckMenuItem* mitem;
2356 
2357  string name = processor->describe_parameter (*i);
2358 
2359  items.push_back (CheckMenuElem (name));
2360  mitem = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
2361 
2362  _subplugin_menu_map[*i] = mitem;
2363 
2364  if (has_visible_automation.find((*i)) != has_visible_automation.end()) {
2365  mitem->set_active(true);
2366  }
2367 
2368  if ((pan = find_processor_automation_node (processor, *i)) == 0) {
2369 
2370  /* new item */
2371 
2372  pan = new ProcessorAutomationNode (*i, mitem, *this);
2373 
2374  rai->lines.push_back (pan);
2375 
2376  } else {
2377 
2378  pan->menu_item = mitem;
2379 
2380  }
2381 
2382  mitem->signal_toggled().connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::processor_menu_item_toggled), rai, pan));
2383  }
2384 
2385  /* add the menu for this processor, because the subplugin
2386  menu is always cleared at the top of processors_changed().
2387  this is the result of some poor design in gtkmm and/or
2388  GTK+.
2389  */
2390 
2391  subplugin_menu.items().push_back (MenuElem (processor->name(), *rai->menu));
2392  rai->valid = true;
2393 }
2394 
2395 void
2398 {
2399  bool showit = pan->menu_item->get_active();
2400  bool redraw = false;
2401 
2402  if (pan->view == 0 && showit) {
2404  redraw = true;
2405  }
2406 
2407  if (pan->view && pan->view->set_marked_for_display (showit)) {
2408  redraw = true;
2409  }
2410 
2411  if (redraw && !no_redraw) {
2412  request_redraw ();
2413  }
2414 }
2415 
2416 void
2418 {
2419  if (c.type == RouteProcessorChange::MeterPointChange) {
2420  /* nothing to do if only the meter point has changed */
2421  return;
2422  }
2423 
2424  using namespace Menu_Helpers;
2425 
2426  for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) {
2427  (*i)->valid = false;
2428  }
2429 
2431 
2432  bool deleted_processor_automation = false;
2433 
2434  for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ) {
2435 
2436  list<ProcessorAutomationInfo*>::iterator tmp;
2437 
2438  tmp = i;
2439  ++tmp;
2440 
2441  if (!(*i)->valid) {
2442 
2443  delete *i;
2444  processor_automation.erase (i);
2445  deleted_processor_automation = true;
2446 
2447  }
2448 
2449  i = tmp;
2450  }
2451 
2452  if (deleted_processor_automation && !no_redraw) {
2453  request_redraw ();
2454  }
2455 }
2456 
2459 {
2461 
2462  if ((pan = find_processor_automation_node (processor, what)) != 0) {
2463  if (pan->view) {
2464  pan->view->line();
2465  }
2466  }
2467 
2469 }
2470 
2471 void
2473 {
2474  for (ProcessorAutomationCurves::iterator i = processor_automation_curves.begin(); i != processor_automation_curves.end(); ++i) {
2475  (*i)->reset();
2476  }
2477 }
2478 
2479 bool
2481 {
2482  /* we do not allow track name changes if it is record enabled
2483  */
2484  return !_route->record_enabled();
2485 }
2486 
2487 void
2489 {
2491 }
2492 
2493 void
2495 {
2497  return;
2498  }
2499 
2500  if (apply_to_selection) {
2502  } else {
2503 
2504  if (_view) {
2505  _view->set_layer_display (d);
2506  }
2507 
2508  set_gui_property (X_("layer-display"), enum_2_string (d));
2509  }
2510 }
2511 
2514 {
2515  if (_view) {
2516  return _view->layer_display ();
2517  }
2518 
2519  /* we don't know, since we don't have a _view, so just return something */
2520  return Overlaid;
2521 }
2522 
2523 
2524 
2527 {
2528  AutomationTracks::iterator i = _automation_tracks.find(param);
2529  if (i != _automation_tracks.end()) {
2530  return i->second;
2531  } else {
2533  }
2534 }
2535 
2536 void
2538 {
2540 }
2541 
2542 void
2544 {
2545  clear_meter ();
2547 }
2548 
2549 void
2551 {
2552  reset_meter ();
2553 }
2554 
2555 void
2557 {
2558  if (ARDOUR_UI::config()->get_show_track_meters()) {
2559  int meter_width = 3;
2560  if (_route && _route->shared_peak_meter()->input_streams().n_total() == 1) {
2561  meter_width = 6;
2562  }
2563  gm.get_level_meter().setup_meters (height - 9, meter_width);
2564  } else {
2565  hide_meter ();
2566  }
2567 }
2568 
2569 void
2571 {
2573 }
2574 
2575 void
2577 {
2579  reset_meter();
2580  if (_route && !no_redraw && ARDOUR_UI::config()->get_show_track_meters()) {
2581  request_redraw ();
2582  }
2583  // reset peak when meter point changes
2585 }
2586 
2587 void
2588 RouteTimeAxisView::io_changed (IOChange /*change*/, void */*src*/)
2589 {
2590  reset_meter ();
2591  if (_route && !no_redraw) {
2592  request_redraw ();
2593  }
2594 }
2595 
2596 void
2598 {
2599  using namespace Menu_Helpers;
2600 
2601  if (!_underlay_streams.empty()) {
2602  MenuList& parent_items = parent_menu->items();
2603  Menu* gs_menu = manage (new Menu);
2604  gs_menu->set_name ("ArdourContextMenu");
2605  MenuList& gs_items = gs_menu->items();
2606 
2607  parent_items.push_back (MenuElem (_("Underlays"), *gs_menu));
2608 
2609  for(UnderlayList::iterator it = _underlay_streams.begin(); it != _underlay_streams.end(); ++it) {
2610  gs_items.push_back(MenuElem(string_compose(_("Remove \"%1\""), (*it)->trackview().name()),
2611  sigc::bind(sigc::mem_fun(*this, &RouteTimeAxisView::remove_underlay), *it)));
2612  }
2613  }
2614 }
2615 
2616 bool
2618 {
2619  if (!underlay_xml_node) {
2620  return false;
2621  }
2622 
2624  XMLNodeConstIterator niter;
2625  XMLNode *child_node;
2626 
2627  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2628  child_node = *niter;
2629 
2630  if (child_node->name() != "Underlay") {
2631  continue;
2632  }
2633 
2634  XMLProperty* prop = child_node->property ("id");
2635  if (prop) {
2636  PBD::ID id (prop->value());
2637 
2639 
2640  if (v) {
2641  add_underlay(v->view(), false);
2642  }
2643  }
2644  }
2645 
2646  return false;
2647 }
2648 
2649 void
2651 {
2652  if (!v) {
2653  return;
2654  }
2655 
2656  RouteTimeAxisView& other = v->trackview();
2657 
2658  if (find(_underlay_streams.begin(), _underlay_streams.end(), v) == _underlay_streams.end()) {
2659  if (find(other._underlay_mirrors.begin(), other._underlay_mirrors.end(), this) != other._underlay_mirrors.end()) {
2660  fatal << _("programming error: underlay reference pointer pairs are inconsistent!") << endmsg;
2661  abort(); /*NOTREACHED*/
2662  }
2663 
2664  _underlay_streams.push_back(v);
2665  other._underlay_mirrors.push_back(this);
2666 
2667  v->foreach_regionview(sigc::mem_fun(*this, &RouteTimeAxisView::add_ghost));
2668 
2669 #ifdef GUI_OBJECT_STATE_FIX_REQUIRED
2670  if (update_xml) {
2671  if (!underlay_xml_node) {
2672  underlay_xml_node = xml_node->add_child("Underlays");
2673  }
2674 
2675  XMLNode* node = underlay_xml_node->add_child("Underlay");
2676  XMLProperty* prop = node->add_property("id");
2677  prop->set_value(v->trackview().route()->id().to_s());
2678  }
2679 #endif
2680  }
2681 }
2682 
2683 void
2685 {
2686  if (!v) {
2687  return;
2688  }
2689 
2690  UnderlayList::iterator it = find(_underlay_streams.begin(), _underlay_streams.end(), v);
2691  RouteTimeAxisView& other = v->trackview();
2692 
2693  if (it != _underlay_streams.end()) {
2694  UnderlayMirrorList::iterator gm = find(other._underlay_mirrors.begin(), other._underlay_mirrors.end(), this);
2695 
2696  if (gm == other._underlay_mirrors.end()) {
2697  fatal << _("programming error: underlay reference pointer pairs are inconsistent!") << endmsg;
2698  abort(); /*NOTREACHED*/
2699  }
2700 
2701  v->foreach_regionview(sigc::mem_fun(*this, &RouteTimeAxisView::remove_ghost));
2702 
2703  _underlay_streams.erase(it);
2704  other._underlay_mirrors.erase(gm);
2705 
2706  if (underlay_xml_node) {
2708  }
2709  }
2710 }
2711 
2712 void
2714 {
2715  if (_route && _route->solo_safe()) {
2717  } else {
2719  }
2720  if (Config->get_solo_control_is_listen_control()) {
2721  switch (Config->get_listen_position()) {
2722  case AfterFaderListen:
2723  solo_button->set_text (S_("AfterFader|A"));
2724  ARDOUR_UI::instance()->set_tip (*solo_button, _("After-fade listen (AFL)"));
2725  break;
2726  case PreFaderListen:
2727  solo_button->set_text (S_("PreFader|P"));
2728  ARDOUR_UI::instance()->set_tip (*solo_button, _("Pre-fade listen (PFL)"));
2729  break;
2730  }
2731  } else {
2732  solo_button->set_text (S_("Solo|S"));
2733  ARDOUR_UI::instance()->set_tip (*solo_button, _("Solo"));
2734  }
2735  mute_button->set_text (S_("Mute|M"));
2736 }
2737 
2738 Gtk::CheckMenuItem*
2740 {
2741  ParameterMenuMap::iterator i = _main_automation_menu_map.find (param);
2742  if (i != _main_automation_menu_map.end()) {
2743  return i->second;
2744  }
2745 
2746  i = _subplugin_menu_map.find (param);
2747  if (i != _subplugin_menu_map.end()) {
2748  return i->second;
2749  }
2750 
2751  return 0;
2752 }
2753 
2754 void
2756 {
2758  if (!c) {
2759  error << "Route has no gain automation, unable to add automation track view." << endmsg;
2760  return;
2761  }
2762 
2764  _route, _route->amp(), c, param,
2765  _editor,
2766  *this,
2767  false,
2768  parent_canvas,
2769  _route->amp()->describe_parameter(param)));
2770 
2771  if (_view) {
2773  }
2774 
2776 }
2777 
2778 void
2780 {
2781  boost::shared_ptr<AutomationControl> c = _route->trim()->gain_control();
2782  if (!c || ! _route->trim()->active()) {
2783  return;
2784  }
2785 
2787  _route, _route->trim(), c, param,
2788  _editor,
2789  *this,
2790  false,
2791  parent_canvas,
2792  _route->trim()->describe_parameter(param)));
2793 
2794  if (_view) {
2796  }
2797 
2799 }
2800 
2801 void
2803 {
2805  if (!c) {
2806  error << "Route has no mute automation, unable to add automation track view." << endmsg;
2807  return;
2808  }
2809 
2811  _route, _route, c, param,
2812  _editor,
2813  *this,
2814  false,
2815  parent_canvas,
2816  _route->describe_parameter(param)));
2817 
2818  if (_view) {
2820  }
2821 
2823 }
2824 
2825 static
2827 {
2828  l->push_back (rv->region());
2829 }
2830 
2831 RegionView*
2833 {
2834  /* as of may 2011, we do not offer uncombine for MIDI tracks
2835  */
2836 
2837  if (!is_audio_track()) {
2838  return 0;
2839  }
2840 
2841  if (!_view) {
2842  return 0;
2843  }
2844 
2845  RegionList selected_regions;
2847 
2848  _view->foreach_selected_regionview (sigc::bind (sigc::ptr_fun (add_region_to_list), &selected_regions));
2849 
2850  if (selected_regions.size() < 2) {
2851  return 0;
2852  }
2853 
2854  playlist->clear_changes ();
2855  boost::shared_ptr<Region> compound_region = playlist->combine (selected_regions);
2856 
2857  _session->add_command (new StatefulDiffCommand (playlist));
2858  /* make the new region be selected */
2859 
2860  return _view->find_view (compound_region);
2861 }
2862 
2863 void
2865 {
2866  /* as of may 2011, we do not offer uncombine for MIDI tracks
2867  */
2868  if (!is_audio_track()) {
2869  return;
2870  }
2871 
2872  if (!_view) {
2873  return;
2874  }
2875 
2876  RegionList selected_regions;
2878 
2879  /* have to grab selected regions first because the uncombine is going
2880  * to change that in the middle of the list traverse
2881  */
2882 
2883  _view->foreach_selected_regionview (sigc::bind (sigc::ptr_fun (add_region_to_list), &selected_regions));
2884 
2885  playlist->clear_changes ();
2886 
2887  for (RegionList::iterator i = selected_regions.begin(); i != selected_regions.end(); ++i) {
2888  playlist->uncombine (*i);
2889  }
2890 
2891  _session->add_command (new StatefulDiffCommand (playlist));
2892 }
2893 
2894 string
2896 {
2897  return string_compose ("rtav %1", _route->id().to_s());
2898 }
2899 
2900 
2901 void
2903 {
2905 
2907  if (a) {
2908  for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
2909  if (i->second == a) {
2910  _automation_tracks.erase (i);
2911  return;
2912  }
2913  }
2914  }
2915 }
LayerDisplay layer_display() const
void set_route_active(bool, bool)
Definition: route_ui.cc:1687
void blink_rec_display(bool onoff)
Gtk::Menu * display_menu
RegionView * find_view(boost::shared_ptr< const ARDOUR::Region >)
Definition: streamview.cc:481
bool transport_rolling() const
Definition: session.h:592
boost::shared_ptr< ARDOUR::Processor > processor
static PBD::Signal1< void, TimeAxisView * > CatchDeletion
void set_align_choice(AlignChoice, bool force=false)
Definition: track.cc:859
std::list< ProcessorAutomationInfo * > processor_automation
int use_copy_playlist()
Definition: track.cc:829
void automation_track_hidden(Evoral::Parameter param)
Gdk::Color color() const
Definition: route_ui.cc:2138
void remove_child(boost::shared_ptr< TimeAxisView >)
void open_comment_editor()
Definition: route_ui.cc:1627
void create_trim_automation_child(const Evoral::Parameter &, bool)
boost::shared_ptr< ARDOUR::Playlist > playlist() const
LIBPBD_API Transmitter fatal
void ripple(framepos_t at, framecnt_t distance, RegionList *exclude)
Definition: playlist.cc:2812
std::string to_string(T t, std::ios_base &(*f)(std::ios_base &))
Definition: convert.h:53
UnderlayList _underlay_streams
void set_route(boost::shared_ptr< ARDOUR::Route >)
int atoi(const string &s)
Definition: convert.cc:140
void remove_ghost(RegionView *)
bool get_sae() const
Definition: profile.h:48
void conditionally_add_to_selection()
#define ui_bind(f,...)
Definition: gui_thread.h:37
void open_remote_control_id_dialog()
Definition: route_ui.cc:1900
virtual Gtk::CheckMenuItem * automation_child_menu_item(Evoral::Parameter)
sigc::signal< void > signal_clicked
void use_new_playlist(bool prompt, std::vector< boost::shared_ptr< ARDOUR::Playlist > > const &)
const std::string & value() const
Definition: xml++.h:159
PBD::Signal1< void, const PropertyChange & > PropertyChanged
Definition: stateful.h:87
bool is_midi_track() const
Definition: route_ui.cc:1756
void update_gain_sensitive()
Definition: gain_meter.cc:589
boost::shared_ptr< Amp > amp() const
Definition: route.h:194
XMLNode * underlay_xml_node
void take_name_changed(void *src)
ARDOUR::RouteGroup * route_group() const
std::string gui_property(const std::string &property_name) const
Definition: axis_view.cc:67
LIBARDOUR_API PBD::PropertyDescriptor< layer_t > layer
Definition: region.cc:67
bool writable() const
Definition: session.h:173
std::string name() const
static unsigned int name_width_px
Gtk::Menu subplugin_menu
void update_pan_track_visibility()
void choose_color()
Definition: route_ui.cc:1479
bool is_audio_track() const
Definition: route_ui.cc:1744
void fade_range(std::list< AudioRange > &)
Definition: playlist.cc:3192
#define enum_2_string(e)
Definition: enumwriter.h:97
bool touched(double top, double bot)
Gtk::CheckMenuItem * trim_automation_item
void set_layer_display(LayerDisplay)
Definition: streamview.cc:667
void clear_meters(bool reset_highlight=true)
Definition: level_meter.cc:496
StreamView * _view
PBD::Signal0< void > FreezeChange
Definition: track.h:164
ArdourButton playlist_button
virtual ~RouteTimeAxisView()
const DataType & data_type() const
Definition: playlist.h:113
void edit_input_configuration()
Definition: route_ui.cc:486
virtual void set_height(uint32_t h, TrackHeightMode m=OnlySelf)
Definition: ardour_ui.h:130
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
virtual void hide_timestretch()
static ARDOUR_UI * instance()
Definition: ardour_ui.h:187
void cut_copy_clear(Selection &, Editing::CutCopyOp)
LIBARDOUR_API PBD::PropertyDescriptor< std::string > name
PBD::Signal0< void > meter_change
Definition: route.h:315
virtual int set_height(double)
Definition: streamview.cc:115
virtual bool controls_ebox_scroll(GdkEventScroll *)
const std::string & name() const
Definition: xml++.h:104
std::string resolve_new_group_playlist_name(std::string &, std::vector< boost::shared_ptr< ARDOUR::Playlist > > const &)
void set_fader_name(const char *name)
Definition: gain_meter.cc:583
int use_new_playlist()
Definition: track.cc:841
boost::shared_ptr< Pannable > pannable() const
Definition: route.cc:4023
Lists of selected things.
Definition: selection.h:66
bool solo_safe() const
Definition: route.cc:804
void add_command(Command *const cmd)
Definition: session.h:787
boost::shared_ptr< ARDOUR::Region > find_next_region(framepos_t pos, ARDOUR::RegionPoint, int32_t dir)
void add_underlay(StreamView *, bool update_xml=true)
void add_processor_automation_curve(boost::shared_ptr< ARDOUR::Processor > r, Evoral::Parameter)
Children children
boost::shared_ptr< Control > control(const Parameter &id, bool create_if_missing=false)
Definition: ControlSet.cpp:73
Representation of the interface of the Editor class.
boost::shared_ptr< AutomationControl > gain_control() const
Definition: route.cc:4042
void get_selectables(ARDOUR::framepos_t, ARDOUR::framepos_t, double, double, std::list< Selectable * > &, bool within=false)
Definition: streamview.cc:551
void build_underlay_menu(Gtk::Menu *)
void set_layer_display(LayerDisplay d, bool apply_to_selection=false)
RouteTimeAxisView & trackview()
Definition: streamview.h:66
tuple f
Definition: signals.py:35
void set(std::list< Selectable * > const &)
Definition: selection.cc:1024
virtual void set_route(boost::shared_ptr< ARDOUR::Route >)
Definition: route_ui.cc:226
Definition: Beats.hpp:239
Gtk::Table controls_table
LIBPBD_API Transmitter error
void clear_owned_changes()
Definition: playlist.cc:2054
ArdourCanvas::Canvas & parent_canvas
const XMLNodeList & children(const std::string &str=std::string()) const
Definition: xml++.cc:329
virtual int set_mode(TrackMode)
Definition: track.h:50
bool set_name(const std::string &str)
Definition: route.cc:3870
RouteGroupMenu * route_group_menu
boost::shared_ptr< Panner > panner() const
Definition: route.cc:4029
void add_existing_processor_automation_curves(boost::weak_ptr< ARDOUR::Processor >)
bool is_auditioner() const
Definition: route.h:110
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
virtual void select_all_tracks()=0
guint modifier
void uncombine(boost::shared_ptr< Region >)
Definition: playlist.cc:3028
SessionConfiguration config
Definition: session.h:866
boost::shared_ptr< PeakMeter > shared_peak_meter() const
Definition: route.h:198
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
XMLNode * add_child(const char *)
Definition: xml++.cc:351
uint32_t current_height() const
LIBPBD_API void strip_whitespace_edges(std::string &str)
AlignChoice alignment_choice() const
Definition: track.cc:795
void set_samples_per_pixel(double)
virtual void remove_tracks()=0
float update_meters()
Definition: level_meter.cc:127
virtual void copy_playlists(TimeAxisView *)=0
#define ENSURE_GUI_THREAD(obj, method,...)
Definition: gui_thread.h:34
void set_tweaks(Tweaks)
virtual bool set_marked_for_display(bool)
Definition: axis_view.cc:87
#define invalidator(x)
Definition: gui_thread.h:40
void set_elements(Element)
void use_playlist(Gtk::RadioMenuItem *item, boost::weak_ptr< ARDOUR::Playlist > wpl)
Gtk::HBox name_hbox
virtual void name_entry_changed()
boost::shared_ptr< Region > combine(const RegionList &)
Definition: playlist.cc:2898
void set_initial_text(std::string txt)
Definition: prompter.h:50
void set_selected_regionviews(RegionSelection &)
Definition: streamview.cc:524
bool ignore_toggle
Definition: route_ui.h:94
virtual void build_display_menu()
Definition: id.h:32
static UI * instance()
Definition: gtk_ui.h:119
void build(ARDOUR::WeakRouteList const &)
virtual void clear_playlists(TimeAxisView *)=0
void set_track_mode(ARDOUR::TrackMode, bool apply_to_selection=false)
std::list< XMLNode * > XMLNodeList
Definition: xml++.h:44
void setup_meters(int len=0, int width=3, int thin=2)
Definition: level_meter.cc:237
std::vector< ProcessorAutomationNode * > lines
void update_trim_track_visibility()
virtual void add_processor_to_subplugin_menu(boost::weak_ptr< ARDOUR::Processor >)
virtual void show_existing_automation(bool apply_to_selection=false)
boost::shared_ptr< Amp > trim() const
Definition: route.h:195
void route_property_changed(const PBD::PropertyChange &)
#define _(Text)
Definition: i18n.h:11
void show_timestretch(framepos_t start, framepos_t end, int layers, int layer)
ProcessorAutomationNode * find_processor_automation_node(boost::shared_ptr< ARDOUR::Processor > i, Evoral::Parameter)
GainMeterBase gm
void set_height(uint32_t h, TrackHeightMode m=OnlySelf)
void foreach_selected_regionview(sigc::slot< void, RegionView * > slot)
Definition: streamview.cc:514
void add(std::list< Selectable * > const &)
Definition: selection.cc:1045
void processor_automation_track_hidden(ProcessorAutomationNode *, boost::shared_ptr< ARDOUR::Processor >)
ArdourButton * rec_enable_button
Definition: route_ui.h:102
int64_t track_number() const
Definition: route.h:302
ArdourCanvas::Container * _canvas_display
virtual void show_timestretch(framepos_t start, framepos_t end, int layers, int layer)
void increase_n_playlists(ARDOUR::DataType t, size_t delta=1)
Definition: item_counts.h:45
void create_gain_automation_child(const Evoral::Parameter &, bool)
boost::shared_ptr< ARDOUR::Route > _route
Definition: route_ui.h:87
static Glib::RefPtr< Gtk::SizeGroup > controls_meters_size_group
RouteTimeAxisView(PublicEditor &, ARDOUR::Session *, ArdourCanvas::Canvas &canvas)
void toggle(std::list< Selectable * > const &)
Definition: selection.cc:991
ArdourButton automation_button
virtual void new_playlists(TimeAxisView *)=0
virtual bool record_enabled() const
Definition: route.h:131
void foreach_regionview(sigc::slot< void, RegionView * > slot)
Definition: streamview.cc:506
TrackMode
Definition: types.h:198
uint32_t gdk_color_to_rgba(Gdk::Color const &)
Definition: utils.cc:285
RegionView * combine_regions()
ArdourButton * solo_button
Definition: route_ui.h:101
#define X_(Text)
Definition: i18n.h:13
virtual void hide_track_in_display(TimeAxisView *tv, bool apply_to_selection=false)=0
LIBARDOUR_API PBD::PropertyDescriptor< bool > automatic
Definition: region.cc:53
ArdourCanvas::Container * _ghost_group
virtual void label_view()
int64_t framecnt_t
Definition: types.h:76
PBD::Signal2< void, std::string, void * > gui_changed
Definition: route.h:324
void get_inverted_selectables(Selection &, std::list< Selectable * > &)
PBD::Signal0< void > track_number_changed
Definition: route.h:301
XMLProperty * property(const char *)
Definition: xml++.cc:413
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
virtual void append_extra_display_menu_items()
#define string_2_enum(str, e)
Definition: enumwriter.h:98
boost::shared_ptr< Region > find_next_region(framepos_t frame, RegionPoint point, int dir)
Definition: playlist.cc:1905
void add_ghost(RegionView *)
virtual PlaylistSelector & playlist_selector() const =0
boost::shared_ptr< ARDOUR::Region > region() const
Definition: region_view.h:66
void set_prompt(std::string prompt)
Definition: prompter.h:46
void remove_underlay(StreamView *)
virtual void blink_rec_display(bool onoff)
Definition: route_ui.cc:1252
bool can_edit_name() const
Definition: enums.h:35
void setup_processor_menu_and_curves()
int use_playlist(boost::shared_ptr< Playlist >)
Definition: track.cc:819
ProcessorAutomationCurves processor_automation_curves
void set_selected_regionviews(RegionSelection &)
Gtkmm2ext::VisualState visual_state() const
Definition: cairo_widget.h:41
virtual framecnt_t get_current_zoom() const =0
virtual std::string describe_parameter(Evoral::Parameter param)
Definition: automatable.cc:160
void set_align_choice(Gtk::RadioMenuItem *, ARDOUR::AlignChoice, bool apply_to_selection=false)
bool string_is_affirmative(const std::string &str)
Definition: convert.cc:282
ArdourCanvas::Container * canvas_display()
virtual void show_all_automation(bool apply_to_selection=false)
framepos_t find_next_region_boundary(framepos_t frame, int dir)
Definition: playlist.cc:1965
virtual void show_selection(TimeSelection &)
bool set_name(const std::string &str)
Definition: playlist.cc:372
int remove(boost::shared_ptr< Route >)
Definition: route_group.cc:161
Definition: amp.h:29
bool is_child(TimeAxisView *)
void request_redraw()
Definition: route_ui.cc:2100
void set_fixed_colors(const uint32_t active_color, const uint32_t inactive_color)
const PBD::ID & id() const
Definition: stateful.h:68
ARDOUR::Session * session() const
Definition: axis_view.h:52
boost::shared_ptr< AutomationTimeAxisView > mute_track
bool is_active() const
Definition: route_group.h:66
std::string to_s() const
Definition: id.cc:78
Gtk::Menu * _size_menu
boost::shared_ptr< ARDOUR::Track > track() const
Definition: route_ui.cc:1738
bool enabled_property(PBD::PropertyID)
Definition: route_group.cc:516
void set_visual_state(Gtkmm2ext::VisualState)
void build_size_menu()
void show_selection(TimeSelection &)
void selection_click(GdkEventButton *)
#define gui_context()
Definition: gui_thread.h:36
Definition: enums.h:36
PBD::Signal0< void > SpeedChanged
Definition: track.h:168
void region_view_added(RegionView *)
virtual void create_automation_child(const Evoral::Parameter &param, bool show)=0
boost::shared_ptr< Playlist > playlist()
Definition: track.cc:590
void foreach_processor(boost::function< void(boost::weak_ptr< Processor >)> method)
Definition: route.h:203
virtual Selection & get_cut_buffer() const =0
LIBARDOUR_API PBD::PropertyDescriptor< bool > mute
Definition: route_group.cc:45
static void add_region_to_list(RegionView *rv, RegionList *l)
bool route_name_internal(std::string) const
Definition: session.cc:4552
AutomationType
Definition: types.h:121
#define DEBUG_TRACE(bits, str)
Definition: debug.h:55
void fade_range(TimeSelection &)
int64_t framepos_t
Definition: types.h:66
virtual Selection & get_selection() const =0
void add_automation_child(Evoral::Parameter param, boost::shared_ptr< AutomationTimeAxisView > track, bool show=true)
void set_selected_points(PointSelection &)
void ensure_pan_views(bool show=true)
PlaylistSelection playlists
Definition: selection.h:85
virtual int set_samples_per_pixel(double)
Definition: streamview.cc:135
LevelMeterHBox & get_level_meter() const
Definition: gain_meter.h:91
AutomationTracks _automation_tracks
LIBARDOUR_API PBD::PropertyDescriptor< bool > regions
Definition: playlist.cc:51
T * get() const
Definition: shared_ptr.hpp:268
Gtk::Menu * automation_action_menu
virtual RouteTimeAxisView * get_route_view_by_route_id(const PBD::ID &id) const =0
PBD::Signal1< void, std::string > ParameterChanged
Definition: configuration.h:44
LIBARDOUR_API PBD::PropertyDescriptor< bool > active
Definition: route_group.cc:43
LIBARDOUR_API RuntimeProfile * Profile
Definition: globals.cc:120
void get_result(std::string &str, bool strip=true)
Definition: prompter.cc:104
void set_fallthrough_to_parent(bool fall)
bool is_track() const
Definition: route_ui.cc:1732
PBD::Signal0< void > PlaylistChanged
Definition: track.h:166
std::list< boost::shared_ptr< Region > > RegionList
Definition: types.h:87
Gtk::Menu * mode_menu
CutCopyOp
Definition: editing.h:198
TimeAxisView * parent
ItemCounts counts
Count of consumed selection items.
Definition: paste_context.h:37
const Parameter & parameter() const
Definition: Control.hpp:69
void set_tip(Gtk::Widget &w, const gchar *tip)
void call_slot(EventLoop::InvalidationRecord *, const boost::function< void()> &)
Definition: abstract_ui.cc:368
unsigned int char_pixel_width()
boost::shared_ptr< AutomationTimeAxisView > gain_track
bool active() const
Definition: route.h:95
void get_inverted_selectables(Selection &, std::list< Selectable * > &results)
Definition: streamview.cc:602
bool selected(TimeAxisView *)
Definition: selection.cc:920
XMLProperty * add_property(const char *name, const std::string &value)
Gtk::CheckMenuItem * gain_automation_item
ParameterMenuMap _subplugin_menu_map
void processors_changed(ARDOUR::RouteProcessorChange)
virtual void build_automation_action_menu(bool)
Insensitive
Definition: widget_state.h:23
PBD::Signal1< void, RouteProcessorChange > processors_changed
Definition: route.h:312
void create_mute_automation_child(const Evoral::Parameter &, bool)
Glib::RefPtr< Gtk::SizeGroup > controls_button_size_group
Gtk::HBox top_hbox
ARDOUR::framepos_t start()
ArdourCanvas::Container * selection_group
ARDOUR::framepos_t length()
boost::shared_ptr< Playlist > copy(std::list< AudioRange > &, bool result_is_hidden=true)
Definition: playlist.cc:1164
virtual void set_samples_per_pixel(double)
class LIBPBD_API PropertyList
ArdourButton route_group_button
Gtk::Menu * menu()
uint32_t id() const
Definition: Parameter.hpp:49
static void what_has_visible_automation(const boost::shared_ptr< ARDOUR::Automatable > &automatable, std::set< Evoral::Parameter > &visible)
static Selection::Operation selection_type(guint state)
Definition: keyboard.cc:178
LIBARDOUR_API PBD::PropertyDescriptor< bool > solo
Definition: route_group.cc:46
void add_child(boost::shared_ptr< TimeAxisView >)
void reset_peak_display()
Definition: gain_meter.cc:397
virtual framecnt_t get_paste_offset(framepos_t pos, unsigned paste_count, framecnt_t duration)=0
static ARDOUR::framepos_t session_frame_to_track_frame(ARDOUR::framepos_t session_frame, double speed)
Definition: types.h:688
bool is_master() const
Definition: route.h:111
Gtkmm2ext::SliderController & get_gain_slider() const
Definition: gain_meter.h:92
Gtk::Entry * name_entry
void reset_processor_automation_curves()
ArdourButton * mute_button
Definition: route_ui.h:100
bool parameter_is_midi(AutomationType type)
Definition: xml++.h:95
RouteGroup * route_group() const
void update_track_number_visibility()
std::string name() const
void clear_tracks()
Definition: selection.cc:127
TimeSelection time
Definition: selection.h:83
uint64_t CutNPaste
Definition: debug.cc:29
boost::shared_ptr< RouteList > route_list()
Definition: route_group.h:126
TrackSelection tracks
Definition: selection.h:81
static UIConfiguration * config()
Definition: ardour_ui.h:188
void set_text(const std::string &)
uint32_t track_number_decimals() const
Definition: session.h:268
Gtk::CheckMenuItem * pan_automation_item
void rdiff(std::vector< Command * > &) const
Definition: playlist.cc:2047
boost::shared_ptr< AutomationTimeAxisView > automation_child(Evoral::Parameter param)
void parameter_changed(std::string const &p)
std::list< boost::weak_ptr< Route > > WeakRouteList
Definition: types.h:533
boost::shared_ptr< MuteControllable > mute_control() const
Definition: route.h:414
uint32_t type() const
Definition: Parameter.hpp:47
sigc::signal< void > ColorsChanged
LIBARDOUR_API PBD::PropertyDescriptor< bool > select
Definition: route_group.cc:48
Definition: debug.h:30
boost::shared_ptr< AutomationLine > find_processor_automation_curve(boost::shared_ptr< ARDOUR::Processor > i, Evoral::Parameter)
boost::shared_ptr< IO > input() const
Definition: route.h:89
virtual bool extend_selection_to_track(TimeAxisView &)=0
UnderlayMirrorList _underlay_mirrors
float times
Number of times to paste.
Definition: paste_context.h:36
TrackMode mode() const
Definition: track.h:49
sigc::signal< void > ZoomChanged
virtual void hide_selection()
#define S_(Text)
Definition: i18n.h:18
void edit_output_configuration()
Definition: route_ui.cc:456
boost::shared_ptr< SessionPlaylists > playlists
Definition: session.h:907
LayerDisplay layer_display() const
Definition: streamview.h:80
FreezeState freeze_state() const
Definition: track.cc:175
LayerDisplay
Definition: enums.h:34
bool contains(PropertyDescriptor< T > p) const
Gtk::Menu * playlist_action_menu
void foreach_route_time_axis(Function f)
void set_gui_property(const std::string &property_name, const T &value)
Definition: axis_view.h:66
const_iterator get_nth(ARDOUR::DataType type, size_t nth) const
std::string state_id() const
LIBARDOUR_API GQuark capture
Definition: operations.cc:24
boost::shared_ptr< IO > output() const
Definition: route.h:90
void set_alignment(const float, const float)
AlignStyle alignment_style() const
Definition: track.cc:789
void update_gain_track_visibility()
static uint32_t preset_height(Height)
std::list< boost::shared_ptr< AutomationTimeAxisView > > pan_tracks
bool destructive() const
Definition: track.cc:608
uint32_t height
PublicEditor & _editor
bool paste(ARDOUR::framepos_t, const Selection &, PasteContext &ctx)
void add_commands(std::vector< Command * > const &cmds)
virtual void begin_reversible_selection_op(std::string cmd_name)=0
void update_mute_track_visibility()
void io_changed(ARDOUR::IOChange, void *)
unsigned count
Number of previous pastes to the same position.
Definition: paste_context.h:35
const std::string & set_value(const std::string &v)
Definition: xml++.h:160
uint8_t channel() const
Definition: Parameter.hpp:48
void processor_menu_item_toggled(RouteTimeAxisView::ProcessorAutomationInfo *, RouteTimeAxisView::ProcessorAutomationNode *)
void remove_nodes_and_delete(const std::string &)
void apply_color(uint32_t, ColorTarget t)
Definition: streamview.cc:354
size_t n_playlists(ARDOUR::DataType t) const
Definition: item_counts.h:40
bool marked_for_display() const
Definition: axis_view.cc:80
LIBGTKMM2EXT_API void detach_menu(Gtk::Menu &)
Definition: utils.cc:361
virtual void clear_playlist(boost::shared_ptr< ARDOUR::Playlist >)=0
void show_for(RouteUI *)
AlignChoice
Definition: types.h:168
gint route_group_click(GdkEventButton *)
Gtk::Label name_label
RegionPoint
Definition: types.h:369
XMLNodeList::const_iterator XMLNodeConstIterator
Definition: xml++.h:49
Gtk::CheckMenuItem * mute_automation_item
virtual void remove_child(boost::shared_ptr< TimeAxisView >)
boost::shared_ptr< Playlist > cut(std::list< AudioRange > &, bool result_is_hidden=true)
Definition: playlist.cc:1157
Definition: enums.h:37
virtual void set_controls(boost::shared_ptr< ARDOUR::Route > route, boost::shared_ptr< ARDOUR::PeakMeter > meter, boost::shared_ptr< ARDOUR::Amp > amp)
Definition: gain_meter.cc:185
void clear_changes()
Definition: stateful.cc:184
boost::shared_ptr< AutomationTimeAxisView > view
void hide_meters()
Definition: level_meter.cc:507
double _y_position
void use_copy_playlist(bool prompt, std::vector< boost::shared_ptr< ARDOUR::Playlist > > const &)
bool add(PropertyBase *prop)
boost::shared_ptr< AutomationLine > line()
ArdourButton number_label
ARDOUR::Session * _session
boost::shared_ptr< ARDOUR::Route > route() const
Definition: route_ui.h:76
void get_selectables(ARDOUR::framepos_t start, ARDOUR::framepos_t end, double top, double bot, std::list< Selectable * > &, bool within=false)
void remove_processor_automation_node(ProcessorAutomationNode *pan)
framepos_t find_next_region_boundary(framepos_t pos, int32_t dir)
sigc::signal< void > Hiding
Definition: axis_view.h:56
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
int paste(boost::shared_ptr< Playlist >, framepos_t position, float times)
Definition: playlist.cc:1211
ArdourCanvas::Rectangle * timestretch_rect
virtual void commit_reversible_selection_op()=0
void cleanup_gui_properties()
Definition: axis_view.h:74
bool is_monitor() const
Definition: route.h:112
virtual void hide_all_automation(bool apply_to_selection=false)
double speed() const
Definition: track.cc:759
void popup_error(const std::string &text)
Definition: gtk_ui.cc:665
boost::shared_ptr< AutomationTimeAxisView > trim_track
bool verify_new_route_name(const std::string &name)
Definition: route_ui.cc:1540
ParameterMenuMap _main_automation_menu_map
void toggle_automation_track(const Evoral::Parameter &param)