2 Copyright (C) 2000 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <sigc++/bind.h>
28 #include "pbd/error.h"
30 #include "pbd/stl_delete.h"
31 #include "pbd/whitespace.h"
32 #include "pbd/basename.h"
33 #include "pbd/enumwriter.h"
34 #include "pbd/memento_command.h"
35 #include "pbd/stateful_diff_command.h"
37 #include "gtkmm2ext/gtk_ui.h"
38 #include "gtkmm2ext/selector.h"
39 #include "gtkmm2ext/bindable_button.h"
40 #include "gtkmm2ext/utils.h"
42 #include "ardour/event_type_map.h"
43 #include "ardour/midi_patch_manager.h"
44 #include "ardour/midi_playlist.h"
45 #include "ardour/midi_region.h"
46 #include "ardour/midi_source.h"
47 #include "ardour/midi_track.h"
48 #include "ardour/operations.h"
49 #include "ardour/pannable.h"
50 #include "ardour/panner.h"
51 #include "ardour/panner_shell.h"
52 #include "ardour/playlist.h"
53 #include "ardour/profile.h"
54 #include "ardour/region.h"
55 #include "ardour/region_factory.h"
56 #include "ardour/route.h"
57 #include "ardour/session.h"
58 #include "ardour/session_object.h"
59 #include "ardour/source.h"
60 #include "ardour/track.h"
61 #include "ardour/types.h"
63 #include "ardour_ui.h"
64 #include "ardour_button.h"
65 #include "automation_line.h"
66 #include "automation_time_axis.h"
69 #include "ghostregion.h"
70 #include "gui_thread.h"
72 #include "midi_channel_selector.h"
73 #include "midi_scroomer.h"
74 #include "midi_streamview.h"
75 #include "midi_region_view.h"
76 #include "midi_time_axis.h"
77 #include "piano_roll_header.h"
78 #include "playlist_selector.h"
79 #include "plugin_selector.h"
80 #include "plugin_ui.h"
81 #include "point_selection.h"
83 #include "region_view.h"
84 #include "rgb_macros.h"
85 #include "selection.h"
86 #include "step_editor.h"
88 #include "note_base.h"
90 #include "ardour/midi_track.h"
94 using namespace ARDOUR;
95 using namespace ARDOUR_UI_UTILS;
98 using namespace Gtkmm2ext;
99 using namespace Editing;
102 // Minimum height at which a control is displayed
103 static const uint32_t MIDI_CONTROLS_BOX_MIN_HEIGHT = 160;
104 static const uint32_t KEYBOARD_MIN_HEIGHT = 130;
106 MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session* sess, ArdourCanvas::Canvas& canvas)
107 : AxisView(sess) // virtually inherited
108 , RouteTimeAxisView(ed, sess, canvas)
109 , _ignore_signals(false)
111 , _piano_roll_header(0)
112 , _note_mode(Sustained)
114 , _percussion_mode_item(0)
115 , _color_mode(MeterColors)
116 , _meter_color_mode_item(0)
117 , _channel_color_mode_item(0)
118 , _track_color_mode_item(0)
119 , _channel_selector (0)
120 , _step_edit_item (0)
121 , controller_menu (0)
127 MidiTimeAxisView::set_route (boost::shared_ptr<Route> rt)
131 _view = new MidiStreamView (*this);
134 _piano_roll_header = new PianoRollHeader(*midi_view());
135 _range_scroomer = new MidiScroomer(midi_view()->note_range_adjustment);
136 _range_scroomer->DoubleClicked.connect (
137 sigc::bind (sigc::mem_fun(*this, &MidiTimeAxisView::set_note_range),
138 MidiStreamView::ContentsRange, false));
141 /* This next call will result in our height being set up, so it must come after
142 the creation of the piano roll / range scroomer as their visibility is set up
145 RouteTimeAxisView::set_route (rt);
147 _view->apply_color (_color, StreamView::RegionColor);
149 subplugin_menu.set_name ("ArdourContextMenu");
151 if (!gui_property ("note-range-min").empty ()) {
152 midi_view()->apply_note_range (atoi (gui_property ("note-range-min").c_str()),
153 atoi (gui_property ("note-range-max").c_str()),
157 midi_view()->NoteRangeChanged.connect (
158 sigc::mem_fun (*this, &MidiTimeAxisView::note_range_changed));
159 _view->ContentsHeightChanged.connect (
160 sigc::mem_fun (*this, &MidiTimeAxisView::contents_height_changed));
162 ignore_toggle = false;
164 if (is_midi_track()) {
165 controls_ebox.set_name ("MidiTimeAxisViewControlsBaseUnselected");
166 time_axis_frame.set_name ("MidiTimeAxisViewControlsBaseUnselected");
167 _note_mode = midi_track()->note_mode();
168 } else { // MIDI bus (which doesn't exist yet..)
169 controls_ebox.set_name ("MidiBusControlsBaseUnselected");
170 time_axis_frame.set_name ("MidiBusControlsBaseUnselected");
173 /* if set_state above didn't create a gain automation child, we need to make one */
174 if (automation_child (GainAutomation) == 0) {
175 create_automation_child (GainAutomation, false);
178 /* if set_state above didn't create a mute automation child, we need to make one */
179 if (automation_child (MuteAutomation) == 0) {
180 create_automation_child (MuteAutomation, false);
183 if (_route->panner_shell()) {
184 _route->panner_shell()->Changed.connect (*this, invalidator (*this), boost::bind (&MidiTimeAxisView::ensure_pan_views, this, false), gui_context());
187 /* map current state of the route */
188 ensure_pan_views (false);
190 processors_changed (RouteProcessorChange ());
192 _route->processors_changed.connect (*this, invalidator (*this),
193 boost::bind (&MidiTimeAxisView::processors_changed, this, _1),
197 _piano_roll_header->SetNoteSelection.connect (
198 sigc::mem_fun (*this, &MidiTimeAxisView::set_note_selection));
199 _piano_roll_header->AddNoteSelection.connect (
200 sigc::mem_fun (*this, &MidiTimeAxisView::add_note_selection));
201 _piano_roll_header->ExtendNoteSelection.connect (
202 sigc::mem_fun (*this, &MidiTimeAxisView::extend_note_selection));
203 _piano_roll_header->ToggleNoteSelection.connect (
204 sigc::mem_fun (*this, &MidiTimeAxisView::toggle_note_selection));
206 /* Suspend updates of the StreamView during scroomer drags to speed things up */
207 _range_scroomer->DragStarting.connect (
208 sigc::mem_fun (*midi_view(), &MidiStreamView::suspend_updates));
209 _range_scroomer->DragFinishing.connect (
210 sigc::mem_fun (*midi_view(), &MidiStreamView::resume_updates));
212 /* Put the scroomer and the keyboard in a VBox with a padding
213 label so that they can be reduced in height for stacked-view
217 HSeparator* separator = manage (new HSeparator());
218 separator->set_name("TrackSeparator");
219 separator->set_size_request(-1, 1);
222 VBox* v = manage (new VBox);
223 HBox* h = manage (new HBox);
224 h->pack_end (*_piano_roll_header);
225 h->pack_end (*_range_scroomer);
226 v->pack_start (*separator, false, false);
227 v->pack_start (*h, true, true);
230 top_hbox.remove(scroomer_placeholder);
231 time_axis_hbox.pack_end(*v, false, false, 0);
232 midi_scroomer_size_group->add_widget (*v);
234 controls_ebox.set_name ("MidiTrackControlsBaseUnselected");
235 time_axis_frame.set_name ("MidiTrackControlsBaseUnselected");
236 controls_base_selected_name = "MidiTrackControlsBaseSelected";
237 controls_base_unselected_name = "MidiTrackControlsBaseUnselected";
239 midi_view()->NoteRangeChanged.connect (
240 sigc::mem_fun(*this, &MidiTimeAxisView::update_range));
242 /* ask for notifications of any new RegionViews */
243 _view->RegionViewAdded.connect (
244 sigc::mem_fun(*this, &MidiTimeAxisView::region_view_added));
246 midi_track()->PlaybackChannelModeChanged.connect (*this, invalidator (*this),
247 boost::bind (&MidiTimeAxisView::playback_channel_mode_changed, this),
249 midi_track()->PlaybackChannelMaskChanged.connect (*this, invalidator (*this),
250 boost::bind (&MidiTimeAxisView::playback_channel_mode_changed, this),
252 midi_track()->CaptureChannelModeChanged.connect (*this, invalidator (*this),
253 boost::bind (&MidiTimeAxisView::capture_channel_mode_changed, this),
255 midi_track()->CaptureChannelMaskChanged.connect (*this, invalidator (*this),
256 boost::bind (&MidiTimeAxisView::capture_channel_mode_changed, this),
259 playback_channel_mode_changed ();
260 capture_channel_mode_changed ();
262 if (!_editor.have_idled()) {
263 /* first idle will do what we need */
269 typedef MIDI::Name::MidiPatchManager PatchManager;
271 PatchManager& patch_manager = PatchManager::instance();
273 for (PatchManager::DeviceNamesByMaker::const_iterator m = patch_manager.devices_by_manufacturer().begin();
274 m != patch_manager.devices_by_manufacturer().end(); ++m) {
275 Menu* menu = Gtk::manage(new Menu);
276 Menu_Helpers::MenuList& items = menu->items();
278 // Build manufacturer submenu
279 for (MIDI::Name::MIDINameDocument::MasterDeviceNamesList::const_iterator n = m->second.begin();
280 n != m->second.end(); ++n) {
281 Menu_Helpers::MenuElem elem = Gtk::Menu_Helpers::MenuElem(
283 sigc::bind(sigc::mem_fun(*this, &MidiTimeAxisView::model_changed),
286 items.push_back(elem);
289 // Add manufacturer submenu to selector
290 _midnam_model_selector.AddMenuElem(Menu_Helpers::MenuElem(m->first, *menu));
293 if (gui_property (X_("midnam-model-name")).empty()) {
294 set_gui_property (X_("midnam-model-name"), "Generic");
297 if (gui_property (X_("midnam-custom-device-mode")).empty()) {
298 boost::shared_ptr<MIDI::Name::MasterDeviceNames> device_names = get_device_names();
300 set_gui_property (X_("midnam-custom-device-mode"),
301 *device_names->custom_device_mode_names().begin());
305 ARDOUR_UI::instance()->set_tip (_midnam_model_selector, _("External MIDI Device"));
306 ARDOUR_UI::instance()->set_tip (_midnam_custom_device_mode_selector, _("External Device Mode"));
308 _midi_controls_box.set_homogeneous(false);
309 _midi_controls_box.set_border_width (2);
311 _channel_status_box.set_homogeneous (false);
312 _channel_status_box.set_spacing (4);
314 ArdourButton *channel_selector_button = manage (new ArdourButton(_("Chns")));
315 channel_selector_button->set_name ("route button");
316 ARDOUR_UI::instance()->set_tip (channel_selector_button, _("Click to edit channel settings"));
318 /* fixed sized labels to prevent silly nonsense (though obviously,
319 * they cause their own too)
321 set_size_request_to_display_given_text(_playback_channel_status, "Play: somemo", 2, 2); // TODO use _("Play: all/some")
322 set_size_request_to_display_given_text(_capture_channel_status, "Rec: somemo", 2, 2); // TODO use _("Rec: all/some")
324 _channel_status_box.pack_start (_playback_channel_status, false, false);
325 _channel_status_box.pack_start (_capture_channel_status, false, false);
326 _channel_status_box.pack_end (*channel_selector_button, false, false);
327 _channel_status_box.show_all ();
329 channel_selector_button->signal_clicked.connect (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_channel_selector));
331 _midi_controls_box.pack_start (_channel_status_box, false, false, 10);
333 if (!patch_manager.all_models().empty()) {
335 _midnam_model_selector.show ();
336 _midi_controls_box.pack_start (_midnam_model_selector, false, false, 2);
338 _midnam_custom_device_mode_selector.show ();
340 _midi_controls_box.pack_start (_midnam_custom_device_mode_selector, false, false, 2);
343 model_changed(gui_property(X_("midnam-model-name")));
344 custom_device_mode_changed(gui_property(X_("midnam-custom-device-mode")));
346 controls_vbox.pack_start(_midi_controls_box, false, false);
348 const string color_mode = gui_property ("color-mode");
349 if (!color_mode.empty()) {
350 _color_mode = ColorMode (string_2_enum(color_mode, _color_mode));
351 if (_channel_selector && _color_mode == ChannelColors) {
352 _channel_selector->set_channel_colors(NoteBase::midi_channel_colors);
356 set_color_mode (_color_mode, true, false);
358 const string note_mode = gui_property ("note-mode");
359 if (!note_mode.empty()) {
360 _note_mode = NoteMode (string_2_enum (note_mode, _note_mode));
361 if (_percussion_mode_item) {
362 _percussion_mode_item->set_active (_note_mode == Percussive);
366 /* Look for any GUI object state nodes that represent automation children
367 * that should exist, and create the children.
370 const list<string> gui_ids = gui_object_state().all_ids ();
371 for (list<string>::const_iterator i = gui_ids.begin(); i != gui_ids.end(); ++i) {
374 Evoral::Parameter parameter (0, 0, 0);
376 bool const p = AutomationTimeAxisView::parse_state_id (
377 *i, route_id, has_parameter, parameter);
378 if (p && route_id == _route->id () && has_parameter) {
379 const std::string& visible = gui_object_state().get_string (*i, X_("visible"));
380 create_automation_child (parameter, string_is_affirmative (visible));
386 MidiTimeAxisView::first_idle ()
393 MidiTimeAxisView::~MidiTimeAxisView ()
395 delete _channel_selector;
397 delete _piano_roll_header;
398 _piano_roll_header = 0;
400 delete _range_scroomer;
403 delete controller_menu;
408 MidiTimeAxisView::check_step_edit ()
410 ensure_step_editor ();
411 _step_editor->check_step_edit ();
415 MidiTimeAxisView::model_changed(const std::string& model)
417 set_gui_property (X_("midnam-model-name"), model);
419 const std::list<std::string> device_modes = MIDI::Name::MidiPatchManager::instance()
420 .custom_device_mode_names_by_model(model);
422 _midnam_model_selector.set_text(model);
423 _midnam_custom_device_mode_selector.clear_items();
425 for (std::list<std::string>::const_iterator i = device_modes.begin();
426 i != device_modes.end(); ++i) {
427 _midnam_custom_device_mode_selector.AddMenuElem(
428 Gtk::Menu_Helpers::MenuElem(
429 *i, sigc::bind(sigc::mem_fun(*this, &MidiTimeAxisView::custom_device_mode_changed),
433 if (!device_modes.empty()) {
434 custom_device_mode_changed(device_modes.front());
437 if (device_modes.size() > 1) {
438 _midnam_custom_device_mode_selector.show();
440 _midnam_custom_device_mode_selector.hide();
443 _route->instrument_info().set_external_instrument (model, device_modes.front());
445 // Rebuild controller menu
446 _controller_menu_map.clear ();
447 delete controller_menu;
449 build_automation_action_menu(false);
453 MidiTimeAxisView::custom_device_mode_changed(const std::string& mode)
455 const std::string model = gui_property (X_("midnam-model-name"));
457 set_gui_property (X_("midnam-custom-device-mode"), mode);
458 _midnam_custom_device_mode_selector.set_text(mode);
459 _route->instrument_info().set_external_instrument (model, mode);
463 MidiTimeAxisView::midi_view()
465 return dynamic_cast<MidiStreamView*>(_view);
469 MidiTimeAxisView::set_height (uint32_t h)
471 if (h >= MIDI_CONTROLS_BOX_MIN_HEIGHT) {
472 _midi_controls_box.show ();
474 _midi_controls_box.hide();
477 if (h >= KEYBOARD_MIN_HEIGHT) {
478 if (is_track() && _range_scroomer) {
479 _range_scroomer->show();
481 if (is_track() && _piano_roll_header) {
482 _piano_roll_header->show();
485 if (is_track() && _range_scroomer) {
486 _range_scroomer->hide();
488 if (is_track() && _piano_roll_header) {
489 _piano_roll_header->hide();
493 /* We need to do this after changing visibility of our stuff, as it will
494 eventually trigger a call to Editor::reset_controls_layout_width(),
495 which needs to know if we have just shown or hidden a scroomer /
498 RouteTimeAxisView::set_height (h);
502 MidiTimeAxisView::append_extra_display_menu_items ()
504 using namespace Menu_Helpers;
506 MenuList& items = display_menu->items();
509 Menu *range_menu = manage(new Menu);
510 MenuList& range_items = range_menu->items();
511 range_menu->set_name ("ArdourContextMenu");
513 range_items.push_back (
514 MenuElem (_("Show Full Range"),
515 sigc::bind (sigc::mem_fun(*this, &MidiTimeAxisView::set_note_range),
516 MidiStreamView::FullRange, true)));
518 range_items.push_back (
519 MenuElem (_("Fit Contents"),
520 sigc::bind (sigc::mem_fun(*this, &MidiTimeAxisView::set_note_range),
521 MidiStreamView::ContentsRange, true)));
523 items.push_back (MenuElem (_("Note Range"), *range_menu));
524 items.push_back (MenuElem (_("Note Mode"), *build_note_mode_menu()));
525 items.push_back (MenuElem (_("Channel Selector"),
526 sigc::mem_fun(*this, &MidiTimeAxisView::toggle_channel_selector)));
528 color_mode_menu = build_color_mode_menu();
529 if (color_mode_menu) {
530 items.push_back (MenuElem (_("Color Mode"), *color_mode_menu));
533 items.push_back (SeparatorElem ());
537 MidiTimeAxisView::toggle_channel_selector ()
539 if (!_channel_selector) {
540 _channel_selector = new MidiChannelSelectorWindow (midi_track());
542 if (_color_mode == ChannelColors) {
543 _channel_selector->set_channel_colors(NoteBase::midi_channel_colors);
545 _channel_selector->set_default_channel_color ();
548 _channel_selector->show_all ();
550 _channel_selector->cycle_visibility ();
555 MidiTimeAxisView::build_automation_action_menu (bool for_selection)
557 using namespace Menu_Helpers;
559 /* If we have a controller menu, we need to detach it before
560 RouteTimeAxis::build_automation_action_menu destroys the
561 menu it is attached to. Otherwise GTK destroys
562 controller_menu's gobj, meaning that it can't be reattached
563 below. See bug #3134.
566 if (controller_menu) {
567 detach_menu (*controller_menu);
570 _channel_command_menu_map.clear ();
571 RouteTimeAxisView::build_automation_action_menu (for_selection);
573 MenuList& automation_items = automation_action_menu->items();
575 uint16_t selected_channels = midi_track()->get_playback_channel_mask();
577 if (selected_channels != 0) {
579 automation_items.push_back (SeparatorElem());
581 /* these 2 MIDI "command" types are semantically more like automation
582 than note data, but they are not MIDI controllers. We give them
583 special status in this menu, since they will not show up in the
584 controller list and anyone who actually knows something about MIDI
585 (!) would not expect to find them there.
588 add_channel_command_menu_item (
589 automation_items, _("Bender"), MidiPitchBenderAutomation, 0);
590 automation_items.back().set_sensitive (
591 !for_selection || _editor.get_selection().tracks.size() == 1);
592 add_channel_command_menu_item (
593 automation_items, _("Pressure"), MidiChannelPressureAutomation, 0);
594 automation_items.back().set_sensitive (
595 !for_selection || _editor.get_selection().tracks.size() == 1);
597 /* now all MIDI controllers. Always offer the possibility that we will
598 rebuild the controllers menu since it might need to be updated after
599 a channel mode change or other change. Also detach it first in case
600 it has been used anywhere else.
603 build_controller_menu ();
605 automation_items.push_back (MenuElem (_("Controllers"), *controller_menu));
606 automation_items.back().set_sensitive (
607 !for_selection || _editor.get_selection().tracks.size() == 1);
609 automation_items.push_back (
610 MenuElem (string_compose ("<i>%1</i>", _("No MIDI Channels selected"))));
611 dynamic_cast<Label*> (automation_items.back().get_child())->set_use_markup (true);
616 MidiTimeAxisView::change_all_channel_tracks_visibility (bool yn, Evoral::Parameter param)
618 const uint16_t selected_channels = midi_track()->get_playback_channel_mask();
620 for (uint8_t chn = 0; chn < 16; chn++) {
621 if (selected_channels & (0x0001 << chn)) {
623 Evoral::Parameter fully_qualified_param (param.type(), chn, param.id());
624 Gtk::CheckMenuItem* menu = automation_child_menu_item (fully_qualified_param);
627 menu->set_active (yn);
634 MidiTimeAxisView::add_channel_command_menu_item (Menu_Helpers::MenuList& items,
636 AutomationType auto_type,
639 using namespace Menu_Helpers;
641 /* count the number of selected channels because we will build a different menu
642 structure if there is more than 1 selected.
645 const uint16_t selected_channels = midi_track()->get_playback_channel_mask();
648 for (uint8_t chn = 0; chn < 16; chn++) {
649 if (selected_channels & (0x0001 << chn)) {
658 /* multiple channels - create a submenu, with 1 item per channel */
660 Menu* chn_menu = manage (new Menu);
661 MenuList& chn_items (chn_menu->items());
662 Evoral::Parameter param_without_channel (auto_type, 0, cmd);
664 /* add a couple of items to hide/show all of them */
666 chn_items.push_back (
667 MenuElem (_("Hide all channels"),
668 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::change_all_channel_tracks_visibility),
669 false, param_without_channel)));
670 chn_items.push_back (
671 MenuElem (_("Show all channels"),
672 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::change_all_channel_tracks_visibility),
673 true, param_without_channel)));
675 for (uint8_t chn = 0; chn < 16; chn++) {
676 if (selected_channels & (0x0001 << chn)) {
678 /* for each selected channel, add a menu item for this controller */
680 Evoral::Parameter fully_qualified_param (auto_type, chn, cmd);
681 chn_items.push_back (
682 CheckMenuElem (string_compose (_("Channel %1"), chn+1),
683 sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::toggle_automation_track),
684 fully_qualified_param)));
686 boost::shared_ptr<AutomationTimeAxisView> track = automation_child (fully_qualified_param);
687 bool visible = false;
690 if (track->marked_for_display()) {
695 Gtk::CheckMenuItem* cmi = static_cast<Gtk::CheckMenuItem*>(&chn_items.back());
696 _channel_command_menu_map[fully_qualified_param] = cmi;
697 cmi->set_active (visible);
701 /* now create an item in the parent menu that has the per-channel list as a submenu */
703 items.push_back (MenuElem (label, *chn_menu));
707 /* just one channel - create a single menu item for this command+channel combination*/
709 for (uint8_t chn = 0; chn < 16; chn++) {
710 if (selected_channels & (0x0001 << chn)) {
712 Evoral::Parameter fully_qualified_param (auto_type, chn, cmd);
714 CheckMenuElem (label,
715 sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::toggle_automation_track),
716 fully_qualified_param)));
718 boost::shared_ptr<AutomationTimeAxisView> track = automation_child (fully_qualified_param);
719 bool visible = false;
722 if (track->marked_for_display()) {
727 Gtk::CheckMenuItem* cmi = static_cast<Gtk::CheckMenuItem*>(&items.back());
728 _channel_command_menu_map[fully_qualified_param] = cmi;
729 cmi->set_active (visible);
731 /* one channel only */
738 /** Add a single menu item for a controller on one channel. */
740 MidiTimeAxisView::add_single_channel_controller_item(Menu_Helpers::MenuList& ctl_items,
742 const std::string& name)
744 using namespace Menu_Helpers;
746 const uint16_t selected_channels = midi_track()->get_playback_channel_mask();
747 for (uint8_t chn = 0; chn < 16; chn++) {
748 if (selected_channels & (0x0001 << chn)) {
750 Evoral::Parameter fully_qualified_param (MidiCCAutomation, chn, ctl);
751 ctl_items.push_back (
753 string_compose ("<b>%1</b>: %2 [%3]", ctl, name, int (chn + 1)),
755 sigc::mem_fun (*this, &RouteTimeAxisView::toggle_automation_track),
756 fully_qualified_param)));
757 dynamic_cast<Label*> (ctl_items.back().get_child())->set_use_markup (true);
759 boost::shared_ptr<AutomationTimeAxisView> track = automation_child (
760 fully_qualified_param);
762 bool visible = false;
764 if (track->marked_for_display()) {
769 Gtk::CheckMenuItem* cmi = static_cast<Gtk::CheckMenuItem*>(&ctl_items.back());
770 _controller_menu_map[fully_qualified_param] = cmi;
771 cmi->set_active (visible);
773 /* one channel only */
779 /** Add a submenu with 1 item per channel for a controller on many channels. */
781 MidiTimeAxisView::add_multi_channel_controller_item(Menu_Helpers::MenuList& ctl_items,
783 const std::string& name)
785 using namespace Menu_Helpers;
787 const uint16_t selected_channels = midi_track()->get_playback_channel_mask();
789 Menu* chn_menu = manage (new Menu);
790 MenuList& chn_items (chn_menu->items());
792 /* add a couple of items to hide/show this controller on all channels */
794 Evoral::Parameter param_without_channel (MidiCCAutomation, 0, ctl);
795 chn_items.push_back (
796 MenuElem (_("Hide all channels"),
797 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::change_all_channel_tracks_visibility),
798 false, param_without_channel)));
799 chn_items.push_back (
800 MenuElem (_("Show all channels"),
801 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::change_all_channel_tracks_visibility),
802 true, param_without_channel)));
804 for (uint8_t chn = 0; chn < 16; chn++) {
805 if (selected_channels & (0x0001 << chn)) {
807 /* for each selected channel, add a menu item for this controller */
809 Evoral::Parameter fully_qualified_param (MidiCCAutomation, chn, ctl);
810 chn_items.push_back (
811 CheckMenuElem (string_compose (_("Channel %1"), chn+1),
812 sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::toggle_automation_track),
813 fully_qualified_param)));
815 boost::shared_ptr<AutomationTimeAxisView> track = automation_child (
816 fully_qualified_param);
817 bool visible = false;
820 if (track->marked_for_display()) {
825 Gtk::CheckMenuItem* cmi = static_cast<Gtk::CheckMenuItem*>(&chn_items.back());
826 _controller_menu_map[fully_qualified_param] = cmi;
827 cmi->set_active (visible);
831 /* add the per-channel menu to the list of controllers, with the name of the controller */
832 ctl_items.push_back (MenuElem (string_compose ("<b>%1</b>: %2", ctl, name),
834 dynamic_cast<Label*> (ctl_items.back().get_child())->set_use_markup (true);
837 boost::shared_ptr<MIDI::Name::CustomDeviceMode>
838 MidiTimeAxisView::get_device_mode()
840 using namespace MIDI::Name;
842 boost::shared_ptr<MasterDeviceNames> device_names = get_device_names();
844 return boost::shared_ptr<MIDI::Name::CustomDeviceMode>();
847 return device_names->custom_device_mode_by_name(
848 gui_property (X_("midnam-custom-device-mode")));
851 boost::shared_ptr<MIDI::Name::MasterDeviceNames>
852 MidiTimeAxisView::get_device_names()
854 using namespace MIDI::Name;
856 const std::string model = gui_property (X_("midnam-model-name"));
858 boost::shared_ptr<MIDINameDocument> midnam = MidiPatchManager::instance()
859 .document_by_model(model);
861 return midnam->master_device_names(model);
863 return boost::shared_ptr<MasterDeviceNames>();
868 MidiTimeAxisView::build_controller_menu ()
870 using namespace Menu_Helpers;
872 if (controller_menu) {
873 /* it exists and has not been invalidated by a channel mode change */
877 controller_menu = new Menu; // explicitly managed by us
878 MenuList& items (controller_menu->items());
880 /* create several "top level" menu items for sets of controllers (16 at a
881 time), and populate each one with a submenu for each controller+channel
882 combination covering the currently selected channels for this track
885 const uint16_t selected_channels = midi_track()->get_playback_channel_mask();
887 /* count the number of selected channels because we will build a different menu
888 structure if there is more than 1 selected.
892 for (uint8_t chn = 0; chn < 16; chn++) {
893 if (selected_channels & (0x0001 << chn)) {
900 using namespace MIDI::Name;
901 boost::shared_ptr<MasterDeviceNames> device_names = get_device_names();
903 if (device_names && !device_names->controls().empty()) {
904 /* Controllers names available in midnam file, generate fancy menu */
905 unsigned n_items = 0;
906 unsigned n_groups = 0;
908 /* TODO: This is not correct, should look up the currently applicable ControlNameList
909 and only build a menu for that one. */
910 for (MasterDeviceNames::ControlNameLists::const_iterator l = device_names->controls().begin();
911 l != device_names->controls().end(); ++l) {
912 boost::shared_ptr<ControlNameList> name_list = l->second;
913 Menu* ctl_menu = NULL;
915 for (ControlNameList::Controls::const_iterator c = name_list->controls().begin();
916 c != name_list->controls().end();) {
917 const uint16_t ctl = c->second->number();
918 if (ctl != MIDI_CTL_MSB_BANK && ctl != MIDI_CTL_LSB_BANK) {
919 /* Skip bank select controllers since they're handled specially */
921 /* Create a new submenu */
922 ctl_menu = manage (new Menu);
925 MenuList& ctl_items (ctl_menu->items());
927 add_multi_channel_controller_item(ctl_items, ctl, c->second->name());
929 add_single_channel_controller_item(ctl_items, ctl, c->second->name());
934 if (ctl_menu && (++n_items == 16 || c == name_list->controls().end())) {
935 /* Submenu has 16 items or we're done, add it to controller menu and reset */
937 MenuElem(string_compose(_("Controllers %1-%2"),
938 (16 * n_groups), (16 * n_groups) + n_items - 1),
947 /* No controllers names, generate generic numeric menu */
948 for (int i = 0; i < 127; i += 16) {
949 Menu* ctl_menu = manage (new Menu);
950 MenuList& ctl_items (ctl_menu->items());
952 for (int ctl = i; ctl < i+16; ++ctl) {
953 if (ctl == MIDI_CTL_MSB_BANK || ctl == MIDI_CTL_LSB_BANK) {
954 /* Skip bank select controllers since they're handled specially */
959 add_multi_channel_controller_item(
960 ctl_items, ctl, string_compose(_("Controller %1"), ctl));
962 add_single_channel_controller_item(
963 ctl_items, ctl, string_compose(_("Controller %1"), ctl));
967 /* Add submenu for this block of controllers to controller menu */
969 MenuElem (string_compose (_("Controllers %1-%2"), i, i + 15),
976 MidiTimeAxisView::build_note_mode_menu()
978 using namespace Menu_Helpers;
980 Menu* mode_menu = manage (new Menu);
981 MenuList& items = mode_menu->items();
982 mode_menu->set_name ("ArdourContextMenu");
984 RadioMenuItem::Group mode_group;
986 RadioMenuElem (mode_group,_("Sustained"),
987 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_note_mode),
989 _note_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
990 _note_mode_item->set_active(_note_mode == Sustained);
993 RadioMenuElem (mode_group, _("Percussive"),
994 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_note_mode),
996 _percussion_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
997 _percussion_mode_item->set_active(_note_mode == Percussive);
1003 MidiTimeAxisView::build_color_mode_menu()
1005 using namespace Menu_Helpers;
1007 Menu* mode_menu = manage (new Menu);
1008 MenuList& items = mode_menu->items();
1009 mode_menu->set_name ("ArdourContextMenu");
1011 RadioMenuItem::Group mode_group;
1013 RadioMenuElem (mode_group, _("Meter Colors"),
1014 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_color_mode),
1015 MeterColors, false, true, true)));
1016 _meter_color_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
1017 _meter_color_mode_item->set_active(_color_mode == MeterColors);
1020 RadioMenuElem (mode_group, _("Channel Colors"),
1021 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_color_mode),
1022 ChannelColors, false, true, true)));
1023 _channel_color_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
1024 _channel_color_mode_item->set_active(_color_mode == ChannelColors);
1027 RadioMenuElem (mode_group, _("Track Color"),
1028 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_color_mode),
1029 TrackColor, false, true, true)));
1030 _channel_color_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
1031 _channel_color_mode_item->set_active(_color_mode == TrackColor);
1037 MidiTimeAxisView::set_note_mode(NoteMode mode, bool apply_to_selection)
1039 if (apply_to_selection) {
1040 _editor.get_selection().tracks.foreach_midi_time_axis (
1041 boost::bind (&MidiTimeAxisView::set_note_mode, _1, mode, false));
1043 if (_note_mode != mode || midi_track()->note_mode() != mode) {
1045 midi_track()->set_note_mode(mode);
1046 set_gui_property ("note-mode", enum_2_string(_note_mode));
1047 _view->redisplay_track();
1053 MidiTimeAxisView::set_color_mode (ColorMode mode, bool force, bool redisplay, bool apply_to_selection)
1055 if (apply_to_selection) {
1056 _editor.get_selection().tracks.foreach_midi_time_axis (
1057 boost::bind (&MidiTimeAxisView::set_color_mode, _1, mode, force, redisplay, false));
1059 if (_color_mode == mode && !force) {
1063 if (_channel_selector) {
1064 if (mode == ChannelColors) {
1065 _channel_selector->set_channel_colors(NoteBase::midi_channel_colors);
1067 _channel_selector->set_default_channel_color();
1072 set_gui_property ("color-mode", enum_2_string(_color_mode));
1074 _view->redisplay_track();
1080 MidiTimeAxisView::set_note_range (MidiStreamView::VisibleNoteRange range, bool apply_to_selection)
1082 if (apply_to_selection) {
1083 _editor.get_selection().tracks.foreach_midi_time_axis (
1084 boost::bind (&MidiTimeAxisView::set_note_range, _1, range, false));
1086 if (!_ignore_signals) {
1087 midi_view()->set_note_range(range);
1093 MidiTimeAxisView::update_range()
1095 MidiGhostRegion* mgr;
1097 for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
1098 if ((mgr = dynamic_cast<MidiGhostRegion*>(*i)) != 0) {
1099 mgr->update_range();
1105 MidiTimeAxisView::show_all_automation (bool apply_to_selection)
1107 using namespace MIDI::Name;
1109 if (apply_to_selection) {
1110 _editor.get_selection().tracks.foreach_midi_time_axis (
1111 boost::bind (&MidiTimeAxisView::show_all_automation, _1, false));
1114 // Show existing automation
1115 const set<Evoral::Parameter> params = midi_track()->midi_playlist()->contained_automation();
1117 for (set<Evoral::Parameter>::const_iterator i = params.begin(); i != params.end(); ++i) {
1118 create_automation_child(*i, true);
1121 // Show automation for all controllers named in midnam file
1122 boost::shared_ptr<MasterDeviceNames> device_names = get_device_names();
1123 if (gui_property (X_("midnam-model-name")) != "Generic" &&
1124 device_names && !device_names->controls().empty()) {
1125 const std::string device_mode = gui_property (X_("midnam-custom-device-mode"));
1126 const uint16_t selected_channels = midi_track()->get_playback_channel_mask();
1127 for (uint32_t chn = 0; chn < 16; ++chn) {
1128 if ((selected_channels & (0x0001 << chn)) == 0) {
1129 // Channel not in use
1133 boost::shared_ptr<ChannelNameSet> chan_names = device_names->channel_name_set_by_channel(
1139 boost::shared_ptr<ControlNameList> control_names = device_names->control_name_list(
1140 chan_names->control_list_name());
1141 if (!control_names) {
1145 for (ControlNameList::Controls::const_iterator c = control_names->controls().begin();
1146 c != control_names->controls().end();
1148 const uint16_t ctl = c->second->number();
1149 if (ctl != MIDI_CTL_MSB_BANK && ctl != MIDI_CTL_LSB_BANK) {
1150 /* Skip bank select controllers since they're handled specially */
1151 const Evoral::Parameter param(MidiCCAutomation, chn, ctl);
1152 create_automation_child(param, true);
1159 RouteTimeAxisView::show_all_automation ();
1164 MidiTimeAxisView::show_existing_automation (bool apply_to_selection)
1166 if (apply_to_selection) {
1167 _editor.get_selection().tracks.foreach_midi_time_axis (
1168 boost::bind (&MidiTimeAxisView::show_existing_automation, _1, false));
1171 const set<Evoral::Parameter> params = midi_track()->midi_playlist()->contained_automation();
1173 for (set<Evoral::Parameter>::const_iterator i = params.begin(); i != params.end(); ++i) {
1174 create_automation_child (*i, true);
1178 RouteTimeAxisView::show_existing_automation ();
1182 /** Create an automation track for the given parameter (pitch bend, channel pressure).
1185 MidiTimeAxisView::create_automation_child (const Evoral::Parameter& param, bool show)
1187 if (param.type() == NullAutomation) {
1191 AutomationTracks::iterator existing = _automation_tracks.find (param);
1193 if (existing != _automation_tracks.end()) {
1195 /* automation track created because we had existing data for
1196 * the processor, but visibility may need to be controlled
1197 * since it will have been set visible by default.
1200 existing->second->set_marked_for_display (show);
1209 boost::shared_ptr<AutomationTimeAxisView> track;
1210 boost::shared_ptr<AutomationControl> control;
1213 switch (param.type()) {
1215 case GainAutomation:
1216 create_gain_automation_child (param, show);
1219 case MuteAutomation:
1220 create_mute_automation_child (param, show);
1223 case PluginAutomation:
1224 /* handled elsewhere */
1227 case MidiCCAutomation:
1228 case MidiPgmChangeAutomation:
1229 case MidiPitchBenderAutomation:
1230 case MidiChannelPressureAutomation:
1231 case MidiSystemExclusiveAutomation:
1232 /* These controllers are region "automation" - they are owned
1233 * by regions (and their MidiModels), not by the track. As a
1234 * result there is no AutomationList/Line for the track, but we create
1235 * a controller for the user to write immediate events, so the editor
1236 * can act as a control surface for the present MIDI controllers.
1238 * TODO: Record manipulation of the controller to regions?
1241 control = _route->automation_control(param, true);
1242 track.reset (new AutomationTimeAxisView (
1245 control ? _route : boost::shared_ptr<Automatable> (),
1252 _route->describe_parameter(param)));
1255 _view->foreach_regionview (
1256 sigc::mem_fun (*track.get(), &TimeAxisView::add_ghost));
1259 add_automation_child (param, track, show);
1262 case PanWidthAutomation:
1263 case PanElevationAutomation:
1264 case PanAzimuthAutomation:
1265 ensure_pan_views (show);
1269 error << "MidiTimeAxisView: unknown automation child "
1270 << EventTypeMap::instance().to_symbol(param) << endmsg;
1275 MidiTimeAxisView::route_active_changed ()
1277 RouteUI::route_active_changed ();
1280 if (_route->active()) {
1281 controls_ebox.set_name ("MidiTrackControlsBaseUnselected");
1282 time_axis_frame.set_name ("MidiTrackControlsBaseUnselected");
1283 controls_base_selected_name = "MidiTrackControlsBaseSelected";
1284 controls_base_unselected_name = "MidiTrackControlsBaseUnselected";
1286 controls_ebox.set_name ("MidiTrackControlsBaseInactiveUnselected");
1287 time_axis_frame.set_name ("MidiTrackControlsBaseInactiveUnselected");
1288 controls_base_selected_name = "MidiTrackControlsBaseInactiveSelected";
1289 controls_base_unselected_name = "MidiTrackControlsBaseInactiveUnselected";
1292 if (_route->active()) {
1293 controls_ebox.set_name ("BusControlsBaseUnselected");
1294 time_axis_frame.set_name ("BusControlsBaseUnselected");
1295 controls_base_selected_name = "BusControlsBaseSelected";
1296 controls_base_unselected_name = "BusControlsBaseUnselected";
1298 controls_ebox.set_name ("BusControlsBaseInactiveUnselected");
1299 time_axis_frame.set_name ("BusControlsBaseInactiveUnselected");
1300 controls_base_selected_name = "BusControlsBaseInactiveSelected";
1301 controls_base_unselected_name = "BusControlsBaseInactiveUnselected";
1307 MidiTimeAxisView::set_note_selection (uint8_t note)
1309 uint16_t chn_mask = midi_track()->get_playback_channel_mask();
1311 if (_view->num_selected_regionviews() == 0) {
1312 _view->foreach_regionview (
1313 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_note_selection_region_view),
1316 _view->foreach_selected_regionview (
1317 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_note_selection_region_view),
1323 MidiTimeAxisView::add_note_selection (uint8_t note)
1325 const uint16_t chn_mask = midi_track()->get_playback_channel_mask();
1327 if (_view->num_selected_regionviews() == 0) {
1328 _view->foreach_regionview (
1329 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::add_note_selection_region_view),
1332 _view->foreach_selected_regionview (
1333 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::add_note_selection_region_view),
1339 MidiTimeAxisView::extend_note_selection (uint8_t note)
1341 const uint16_t chn_mask = midi_track()->get_playback_channel_mask();
1343 if (_view->num_selected_regionviews() == 0) {
1344 _view->foreach_regionview (
1345 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::extend_note_selection_region_view),
1348 _view->foreach_selected_regionview (
1349 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::extend_note_selection_region_view),
1355 MidiTimeAxisView::toggle_note_selection (uint8_t note)
1357 const uint16_t chn_mask = midi_track()->get_playback_channel_mask();
1359 if (_view->num_selected_regionviews() == 0) {
1360 _view->foreach_regionview (
1361 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_note_selection_region_view),
1364 _view->foreach_selected_regionview (
1365 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_note_selection_region_view),
1371 MidiTimeAxisView::set_note_selection_region_view (RegionView* rv, uint8_t note, uint16_t chn_mask)
1373 dynamic_cast<MidiRegionView*>(rv)->select_matching_notes (note, chn_mask, false, false);
1377 MidiTimeAxisView::add_note_selection_region_view (RegionView* rv, uint8_t note, uint16_t chn_mask)
1379 dynamic_cast<MidiRegionView*>(rv)->select_matching_notes (note, chn_mask, true, false);
1383 MidiTimeAxisView::extend_note_selection_region_view (RegionView* rv, uint8_t note, uint16_t chn_mask)
1385 dynamic_cast<MidiRegionView*>(rv)->select_matching_notes (note, chn_mask, true, true);
1389 MidiTimeAxisView::toggle_note_selection_region_view (RegionView* rv, uint8_t note, uint16_t chn_mask)
1391 dynamic_cast<MidiRegionView*>(rv)->toggle_matching_notes (note, chn_mask);
1395 MidiTimeAxisView::set_channel_mode (ChannelMode, uint16_t)
1397 /* hide all automation tracks that use the wrong channel(s) and show all those that use
1401 const uint16_t selected_channels = midi_track()->get_playback_channel_mask();
1402 bool changed = false;
1406 for (uint32_t ctl = 0; ctl < 127; ++ctl) {
1408 for (uint32_t chn = 0; chn < 16; ++chn) {
1409 Evoral::Parameter fully_qualified_param (MidiCCAutomation, chn, ctl);
1410 boost::shared_ptr<AutomationTimeAxisView> track = automation_child (fully_qualified_param);
1416 if ((selected_channels & (0x0001 << chn)) == 0) {
1417 /* channel not in use. hiding it will trigger RouteTimeAxisView::automation_track_hidden()
1418 which will cause a redraw. We don't want one per channel, so block that with no_redraw.
1420 changed = track->set_marked_for_display (false) || changed;
1422 changed = track->set_marked_for_display (true) || changed;
1429 /* TODO: Bender, Pressure */
1431 /* invalidate the controller menu, so that we rebuild it next time */
1432 _controller_menu_map.clear ();
1433 delete controller_menu;
1434 controller_menu = 0;
1442 MidiTimeAxisView::automation_child_menu_item (Evoral::Parameter param)
1444 Gtk::CheckMenuItem* m = RouteTimeAxisView::automation_child_menu_item (param);
1449 ParameterMenuMap::iterator i = _controller_menu_map.find (param);
1450 if (i != _controller_menu_map.end()) {
1454 i = _channel_command_menu_map.find (param);
1455 if (i != _channel_command_menu_map.end()) {
1462 boost::shared_ptr<MidiRegion>
1463 MidiTimeAxisView::add_region (framepos_t pos, framecnt_t length, bool commit)
1465 Editor* real_editor = dynamic_cast<Editor*> (&_editor);
1467 real_editor->begin_reversible_command (Operations::create_region);
1468 playlist()->clear_changes ();
1470 real_editor->snap_to (pos, RoundNearest);
1472 boost::shared_ptr<Source> src = _session->create_midi_source_by_stealing_name (view()->trackview().track());
1475 plist.add (ARDOUR::Properties::start, 0);
1476 plist.add (ARDOUR::Properties::length, length);
1477 plist.add (ARDOUR::Properties::name, PBD::basename_nosuffix(src->name()));
1479 boost::shared_ptr<Region> region = (RegionFactory::create (src, plist));
1481 playlist()->add_region (region, pos);
1482 _session->add_command (new StatefulDiffCommand (playlist()));
1485 real_editor->commit_reversible_command ();
1488 return boost::dynamic_pointer_cast<MidiRegion>(region);
1492 MidiTimeAxisView::ensure_step_editor ()
1494 if (!_step_editor) {
1495 _step_editor = new StepEditor (_editor, midi_track(), *this);
1500 MidiTimeAxisView::start_step_editing ()
1502 ensure_step_editor ();
1503 _step_editor->start_step_editing ();
1507 MidiTimeAxisView::stop_step_editing ()
1510 _step_editor->stop_step_editing ();
1514 /** @return channel (counted from 0) to add an event to, based on the current setting
1515 * of the channel selector.
1518 MidiTimeAxisView::get_channel_for_add () const
1520 uint16_t const chn_mask = midi_track()->get_playback_channel_mask();
1522 uint8_t channel = 0;
1524 /* pick the highest selected channel, unless all channels are selected,
1525 which is interpreted to mean channel 1 (zero)
1528 for (uint16_t i = 0; i < 16; ++i) {
1529 if (chn_mask & (1<<i)) {
1535 if (chn_cnt == 16) {
1543 MidiTimeAxisView::note_range_changed ()
1545 set_gui_property ("note-range-min", (int) midi_view()->lowest_note ());
1546 set_gui_property ("note-range-max", (int) midi_view()->highest_note ());
1550 MidiTimeAxisView::contents_height_changed ()
1552 _range_scroomer->queue_resize ();
1556 MidiTimeAxisView::playback_channel_mode_changed ()
1558 switch (midi_track()->get_playback_channel_mode()) {
1560 _playback_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2</i>", _("Play"), _("all")));
1562 case FilterChannels:
1563 _playback_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2</i>", _("Play"), _("some")));
1566 _playback_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2>%3</i>", _("Play"), _("all"), PBD::ffs (midi_track()->get_playback_channel_mask())));
1572 MidiTimeAxisView::capture_channel_mode_changed ()
1574 switch (midi_track()->get_capture_channel_mode()) {
1576 _capture_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2</i>", _("Rec"), _("all")));
1578 case FilterChannels:
1579 _capture_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2</i>", _("Rec"), _("some")));
1582 _capture_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2>%3</i>", _("Rec"), _("all"), PBD::ffs (midi_track()->get_capture_channel_mask())));
1588 MidiTimeAxisView::paste (framepos_t pos, const Selection& selection, PasteContext& ctx)
1590 if (!_editor.internal_editing()) {
1591 // Non-internal paste, paste regions like any other route
1592 return RouteTimeAxisView::paste(pos, selection, ctx);
1595 return midi_view()->paste(pos, selection, ctx);