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"
29 #include "pbd/stl_delete.h"
30 #include "pbd/whitespace.h"
31 #include "pbd/basename.h"
32 #include "pbd/enumwriter.h"
33 #include "pbd/memento_command.h"
35 #include <gtkmm2ext/gtk_ui.h>
36 #include <gtkmm2ext/selector.h>
37 #include <gtkmm2ext/stop_signal.h>
38 #include <gtkmm2ext/bindable_button.h>
39 #include <gtkmm2ext/utils.h>
41 #include "ardour/midi_playlist.h"
42 #include "ardour/midi_diskstream.h"
43 #include "ardour/midi_patch_manager.h"
44 #include "ardour/midi_source.h"
45 #include "ardour/processor.h"
46 #include "ardour/ladspa_plugin.h"
47 #include "ardour/location.h"
48 #include "ardour/playlist.h"
49 #include "ardour/region_factory.h"
50 #include "ardour/session.h"
51 #include "ardour/session_playlist.h"
52 #include "ardour/tempo.h"
53 #include "ardour/utils.h"
55 #include "midi++/names.h"
57 #include "add_midi_cc_track_dialog.h"
58 #include "ardour_ui.h"
59 #include "automation_line.h"
60 #include "automation_time_axis.h"
61 #include "canvas-note-event.h"
62 #include "canvas_impl.h"
63 #include "crossfade_view.h"
66 #include "ghostregion.h"
67 #include "gui_thread.h"
69 #include "midi_scroomer.h"
70 #include "midi_streamview.h"
71 #include "midi_region_view.h"
72 #include "midi_time_axis.h"
73 #include "piano_roll_header.h"
74 #include "playlist_selector.h"
75 #include "plugin_selector.h"
76 #include "plugin_ui.h"
77 #include "point_selection.h"
79 #include "region_view.h"
80 #include "rgb_macros.h"
81 #include "selection.h"
82 #include "simplerect.h"
85 #include "ardour/midi_track.h"
89 using namespace ARDOUR;
92 using namespace Gtkmm2ext;
93 using namespace Editing;
95 // Minimum height at which a control is displayed
96 static const uint32_t MIDI_CONTROLS_BOX_MIN_HEIGHT = 162;
97 static const uint32_t KEYBOARD_MIN_HEIGHT = 140;
99 MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session* sess,
100 boost::shared_ptr<Route> rt, Canvas& canvas)
101 : AxisView(sess) // virtually inherited
102 , RouteTimeAxisView(ed, sess, rt, canvas)
103 , _ignore_signals(false)
105 , _piano_roll_header(0)
106 , _note_mode(Sustained)
108 , _percussion_mode_item(0)
109 , _color_mode(MeterColors)
110 , _meter_color_mode_item(0)
111 , _channel_color_mode_item(0)
112 , _track_color_mode_item(0)
113 , _step_edit_item (0)
114 , _midi_thru_item (0)
115 , default_channel_menu (0)
116 , controller_menu (0)
118 subplugin_menu.set_name ("ArdourContextMenu");
120 _view = new MidiStreamView (*this);
122 ignore_toggle = false;
124 mute_button->set_active (false);
125 solo_button->set_active (false);
127 step_edit_insert_position = 0;
129 if (is_midi_track()) {
130 controls_ebox.set_name ("MidiTimeAxisViewControlsBaseUnselected");
131 _note_mode = midi_track()->note_mode();
132 } else { // MIDI bus (which doesn't exist yet..)
133 controls_ebox.set_name ("MidiBusControlsBaseUnselected");
136 /* map current state of the route */
138 processors_changed (RouteProcessorChange ());
142 set_state (*xml_node, Stateful::loading_state_version);
144 _route->processors_changed.connect (*this, ui_bind (&MidiTimeAxisView::processors_changed, this, _1), gui_context());
147 _piano_roll_header = new PianoRollHeader(*midi_view());
149 _piano_roll_header->AddNoteSelection.connect (sigc::mem_fun (*this, &MidiTimeAxisView::add_note_selection));
150 _piano_roll_header->ExtendNoteSelection.connect (sigc::mem_fun (*this, &MidiTimeAxisView::extend_note_selection));
151 _piano_roll_header->ToggleNoteSelection.connect (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_note_selection));
153 _range_scroomer = new MidiScroomer(midi_view()->note_range_adjustment);
155 controls_hbox.pack_start(*_range_scroomer);
156 controls_hbox.pack_start(*_piano_roll_header);
158 controls_ebox.set_name ("MidiTrackControlsBaseUnselected");
159 controls_base_selected_name = "MidiTrackControlsBaseSelected";
160 controls_base_unselected_name = "MidiTrackControlsBaseUnselected";
162 midi_view()->NoteRangeChanged.connect (sigc::mem_fun(*this, &MidiTimeAxisView::update_range));
164 /* ask for notifications of any new RegionViews */
165 _view->RegionViewAdded.connect (sigc::mem_fun(*this, &MidiTimeAxisView::region_view_added));
169 HBox* midi_controls_hbox = manage(new HBox());
171 MIDI::Name::MidiPatchManager& patch_manager = MIDI::Name::MidiPatchManager::instance();
173 MIDI::Name::MasterDeviceNames::Models::const_iterator m = patch_manager.all_models().begin();
174 for (; m != patch_manager.all_models().end(); ++m) {
175 _model_selector.append_text(m->c_str());
178 _model_selector.signal_changed().connect(sigc::mem_fun(*this, &MidiTimeAxisView::model_changed));
180 _custom_device_mode_selector.signal_changed().connect(
181 sigc::mem_fun(*this, &MidiTimeAxisView::custom_device_mode_changed));
183 // TODO: persist the choice
184 // this initializes the comboboxes and sends out the signal
185 _model_selector.set_active(0);
187 midi_controls_hbox->pack_start(_channel_selector, true, false);
188 if (!patch_manager.all_models().empty()) {
189 _midi_controls_box.pack_start(_model_selector, true, false);
190 _midi_controls_box.pack_start(_custom_device_mode_selector, true, false);
193 _midi_controls_box.pack_start(*midi_controls_hbox, true, true);
195 controls_vbox.pack_start(_midi_controls_box, false, false);
197 boost::shared_ptr<MidiDiskstream> diskstream = midi_track()->midi_diskstream();
199 // restore channel selector settings
200 _channel_selector.set_channel_mode(diskstream->get_channel_mode(),
201 diskstream->get_channel_mask());
202 _channel_selector.mode_changed.connect(
203 sigc::mem_fun(*midi_track()->midi_diskstream(), &MidiDiskstream::set_channel_mode));
204 _channel_selector.mode_changed.connect(
205 sigc::mem_fun(*this, &MidiTimeAxisView::set_channel_mode));
208 if ((prop = xml_node->property ("color-mode")) != 0) {
209 _color_mode = ColorMode (string_2_enum(prop->value(), _color_mode));
210 if (_color_mode == ChannelColors) {
211 _channel_selector.set_channel_colors(CanvasNoteEvent::midi_channel_colors);
215 if ((prop = xml_node->property ("note-mode")) != 0) {
216 _note_mode = NoteMode (string_2_enum(prop->value(), _note_mode));
217 if (_percussion_mode_item) {
218 _percussion_mode_item->set_active (_note_mode == Percussive);
223 MidiTimeAxisView::~MidiTimeAxisView ()
225 delete _piano_roll_header;
226 _piano_roll_header = 0;
228 delete _range_scroomer;
231 delete controller_menu;
234 void MidiTimeAxisView::model_changed()
236 std::list<std::string> device_modes = MIDI::Name::MidiPatchManager::instance()
237 .custom_device_mode_names_by_model(_model_selector.get_active_text());
239 _custom_device_mode_selector.clear_items();
241 for (std::list<std::string>::const_iterator i = device_modes.begin();
242 i != device_modes.end(); ++i) {
243 cerr << "found custom device mode " << *i << " thread_id: " << pthread_self() << endl;
244 _custom_device_mode_selector.append_text(*i);
247 _custom_device_mode_selector.set_active(0);
250 void MidiTimeAxisView::custom_device_mode_changed()
252 _midi_patch_settings_changed.emit(_model_selector.get_active_text(),
253 _custom_device_mode_selector.get_active_text());
257 MidiTimeAxisView::midi_view()
259 return dynamic_cast<MidiStreamView*>(_view);
263 MidiTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
266 xml_node->add_property ("shown-editor", "yes");
268 guint32 ret = TimeAxisView::show_at (y, nth, parent);
273 MidiTimeAxisView::hide ()
276 xml_node->add_property ("shown-editor", "no");
278 TimeAxisView::hide ();
282 MidiTimeAxisView::set_height (uint32_t h)
284 RouteTimeAxisView::set_height (h);
286 if (height >= MIDI_CONTROLS_BOX_MIN_HEIGHT) {
287 _midi_controls_box.show();
289 _midi_controls_box.hide();
292 if (height >= KEYBOARD_MIN_HEIGHT) {
293 if (is_track() && _range_scroomer)
294 _range_scroomer->show();
295 if (is_track() && _piano_roll_header)
296 _piano_roll_header->show();
298 if (is_track() && _range_scroomer)
299 _range_scroomer->hide();
300 if (is_track() && _piano_roll_header)
301 _piano_roll_header->hide();
306 MidiTimeAxisView::append_extra_display_menu_items ()
308 using namespace Menu_Helpers;
310 MenuList& items = display_menu->items();
313 Menu *range_menu = manage(new Menu);
314 MenuList& range_items = range_menu->items();
315 range_menu->set_name ("ArdourContextMenu");
317 range_items.push_back (MenuElem (_("Show Full Range"), sigc::bind (
318 sigc::mem_fun(*this, &MidiTimeAxisView::set_note_range),
319 MidiStreamView::FullRange)));
321 range_items.push_back (MenuElem (_("Fit Contents"), sigc::bind (
322 sigc::mem_fun(*this, &MidiTimeAxisView::set_note_range),
323 MidiStreamView::ContentsRange)));
325 items.push_back (MenuElem (_("Note range"), *range_menu));
326 items.push_back (MenuElem (_("Note mode"), *build_note_mode_menu()));
327 items.push_back (MenuElem (_("Default Channel"), *build_def_channel_menu()));
329 items.push_back (CheckMenuElem (_("MIDI Thru"), sigc::mem_fun(*this, &MidiTimeAxisView::toggle_midi_thru)));
330 _midi_thru_item = dynamic_cast<CheckMenuItem*>(&items.back());
334 MidiTimeAxisView::build_def_channel_menu ()
336 using namespace Menu_Helpers;
338 default_channel_menu = manage (new Menu ());
340 uint8_t defchn = midi_track()->default_channel();
341 MenuList& def_channel_items = default_channel_menu->items();
343 RadioMenuItem::Group dc_group;
345 for (int i = 0; i < 16; ++i) {
347 snprintf (buf, sizeof (buf), "%d", i+1);
349 def_channel_items.push_back (RadioMenuElem (dc_group, buf,
350 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_default_channel), i)));
351 item = dynamic_cast<RadioMenuItem*>(&def_channel_items.back());
352 item->set_active ((i == defchn));
355 return default_channel_menu;
359 MidiTimeAxisView::set_default_channel (int chn)
361 midi_track()->set_default_channel (chn);
365 MidiTimeAxisView::toggle_midi_thru ()
367 if (!_midi_thru_item) {
371 bool view_yn = _midi_thru_item->get_active();
372 if (view_yn != midi_track()->midi_thru()) {
373 midi_track()->set_midi_thru (view_yn);
378 MidiTimeAxisView::build_automation_action_menu ()
380 using namespace Menu_Helpers;
382 RouteTimeAxisView::build_automation_action_menu ();
384 MenuList& automation_items = automation_action_menu->items();
386 uint16_t selected_channels = _channel_selector.get_selected_channels();
388 if (selected_channels != 0) {
390 automation_items.push_back (SeparatorElem());
392 /* these 3 MIDI "command" types are semantically more like automation than note data,
393 but they are not MIDI controllers. We give them special status in this menu, since
394 they will not show up in the controller list and anyone who actually knows
395 something about MIDI (!) would not expect to find them there.
398 add_channel_command_menu_item (automation_items, _("Program Change"), MidiPgmChangeAutomation, MIDI_CMD_PGM_CHANGE);
399 add_channel_command_menu_item (automation_items, _("Bender"), MidiPitchBenderAutomation, MIDI_CMD_BENDER);
400 add_channel_command_menu_item (automation_items, _("Pressure"), MidiChannelPressureAutomation, MIDI_CMD_CHANNEL_PRESSURE);
402 /* now all MIDI controllers. Always offer the possibility that we will rebuild the controllers menu
403 since it might need to be updated after a channel mode change or other change. Also detach it
404 first in case it has been used anywhere else.
407 build_controller_menu ();
408 detach_menu (*controller_menu);
410 automation_items.push_back (SeparatorElem());
411 automation_items.push_back (MenuElem (_("Controllers"), *controller_menu));
413 automation_items.push_back (MenuElem (string_compose ("<i>%1</i>", _("No MIDI Channels selected"))));
419 MidiTimeAxisView::change_all_channel_tracks_visibility (bool yn, Evoral::Parameter param)
421 uint16_t selected_channels = _channel_selector.get_selected_channels();
423 for (uint8_t chn = 0; chn < 16; chn++) {
424 if (selected_channels & (0x0001 << chn)) {
426 Evoral::Parameter fully_qualified_param (param.type(), chn, param.id());
427 RouteAutomationNode* node = automation_track (fully_qualified_param);
429 if (node && node->menu_item) {
430 node->menu_item->set_active (yn);
437 MidiTimeAxisView::add_channel_command_menu_item (Menu_Helpers::MenuList& items, const string& label, AutomationType auto_type, uint8_t cmd)
439 using namespace Menu_Helpers;
441 /* count the number of selected channels because we will build a different menu structure if there is more than 1 selected.
444 uint16_t selected_channels = _channel_selector.get_selected_channels();
447 for (uint8_t chn = 0; chn < 16; chn++) {
448 if (selected_channels & (0x0001 << chn)) {
457 /* multiple channels - create a submenu, with 1 item per channel */
459 Menu* chn_menu = manage (new Menu);
460 MenuList& chn_items (chn_menu->items());
461 Evoral::Parameter param_without_channel (auto_type, 0, cmd);
463 /* add a couple of items to hide/show all of them */
465 chn_items.push_back (MenuElem (_("Hide all channels"),
466 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::change_all_channel_tracks_visibility),
467 false, param_without_channel)));
468 chn_items.push_back (MenuElem (_("Show all channels"),
469 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::change_all_channel_tracks_visibility),
470 true, param_without_channel)));
472 for (uint8_t chn = 0; chn < 16; chn++) {
473 if (selected_channels & (0x0001 << chn)) {
475 /* for each selected channel, add a menu item for this controller */
477 Evoral::Parameter fully_qualified_param (auto_type, chn, cmd);
478 chn_items.push_back (CheckMenuElem (string_compose (_("Channel %1"), chn+1),
479 sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::toggle_automation_track),
480 fully_qualified_param)));
482 RouteAutomationNode* node = automation_track (fully_qualified_param);
483 bool visible = false;
486 if (node->track->marked_for_display()) {
491 CheckMenuItem* cmi = static_cast<CheckMenuItem*>(&chn_items.back());
493 node->menu_item = cmi;
496 cmi->set_active (visible);
498 parameter_menu_map[fully_qualified_param] = cmi;
502 /* now create an item in the parent menu that has the per-channel list as a submenu */
504 items.push_back (MenuElem (label, *chn_menu));
508 /* just one channel - create a single menu item for this command+channel combination*/
510 for (uint8_t chn = 0; chn < 16; chn++) {
511 if (selected_channels & (0x0001 << chn)) {
513 Evoral::Parameter fully_qualified_param (auto_type, chn, cmd);
514 items.push_back (CheckMenuElem (label,
515 sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::toggle_automation_track),
516 fully_qualified_param)));
518 RouteAutomationNode* node = automation_track (fully_qualified_param);
519 bool visible = false;
522 if (node->track->marked_for_display()) {
527 CheckMenuItem* cmi = static_cast<CheckMenuItem*>(&items.back());
529 node->menu_item = cmi;
532 cmi->set_active (visible);
534 parameter_menu_map[fully_qualified_param] = cmi;
536 /* one channel only */
544 MidiTimeAxisView::build_controller_menu ()
546 using namespace Menu_Helpers;
548 if (controller_menu) {
549 /* it exists and has not been invalidated by a channel mode change, so just return it */
553 controller_menu = new Menu; // explicitly managed by us
554 MenuList& items (controller_menu->items());
556 /* create several "top level" menu items for sets of controllers (16 at a time), and populate each one with a submenu
557 for each controller+channel combination covering the currently selected channels for this track
560 uint16_t selected_channels = _channel_selector.get_selected_channels();
562 /* count the number of selected channels because we will build a different menu structure if there is more than 1 selected.
567 for (uint8_t chn = 0; chn < 16; chn++) {
568 if (selected_channels & (0x0001 << chn)) {
575 /* loop over all 127 MIDI controllers, in groups of 16 */
577 for (int i = 0; i < 127; i += 16) {
579 Menu* ctl_menu = manage (new Menu);
580 MenuList& ctl_items (ctl_menu->items());
583 /* for each controller, consider whether to create a submenu or a single item */
585 for (int ctl = i; ctl < i+16; ++ctl) {
589 /* multiple channels - create a submenu, with 1 item per channel */
591 Menu* chn_menu = manage (new Menu);
592 MenuList& chn_items (chn_menu->items());
594 /* add a couple of items to hide/show this controller on all channels */
596 Evoral::Parameter param_without_channel (MidiCCAutomation, 0, ctl);
597 chn_items.push_back (MenuElem (_("Hide all channels"),
598 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::change_all_channel_tracks_visibility),
599 false, param_without_channel)));
600 chn_items.push_back (MenuElem (_("Show all channels"),
601 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::change_all_channel_tracks_visibility),
602 true, param_without_channel)));
604 for (uint8_t chn = 0; chn < 16; chn++) {
605 if (selected_channels & (0x0001 << chn)) {
607 /* for each selected channel, add a menu item for this controller */
609 Evoral::Parameter fully_qualified_param (MidiCCAutomation, chn, ctl);
610 chn_items.push_back (CheckMenuElem (string_compose (_("Channel %1"), chn+1),
611 sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::toggle_automation_track),
612 fully_qualified_param)));
614 RouteAutomationNode* node = automation_track (fully_qualified_param);
615 bool visible = false;
618 if (node->track->marked_for_display()) {
623 CheckMenuItem* cmi = static_cast<CheckMenuItem*>(&chn_items.back());
626 node->menu_item = cmi;
629 cmi->set_active (visible);
631 parameter_menu_map[fully_qualified_param] = cmi;
635 /* add the per-channel menu to the list of controllers, with the name of the controller */
637 ctl_items.push_back (MenuElem (midi_name (ctl), *chn_menu));
641 /* just one channel - create a single menu item for this ctl+channel combination*/
643 for (uint8_t chn = 0; chn < 16; chn++) {
644 if (selected_channels & (0x0001 << chn)) {
646 Evoral::Parameter fully_qualified_param (MidiCCAutomation, chn, ctl);
647 ctl_items.push_back (CheckMenuElem (_route->describe_parameter (fully_qualified_param),
648 sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::toggle_automation_track),
649 fully_qualified_param)));
651 RouteAutomationNode* node = automation_track (fully_qualified_param);
652 bool visible = false;
655 if (node->track->marked_for_display()) {
660 CheckMenuItem* cmi = static_cast<CheckMenuItem*>(&ctl_items.back());
662 node->menu_item = cmi;
665 cmi->set_active (visible);
668 parameter_menu_map[fully_qualified_param] = cmi;
669 /* one channel only */
676 /* add the menu for this block of controllers to the overall controller menu */
678 items.push_back (MenuElem (string_compose (_("Controllers %1-%2"), i+1, i+16), *ctl_menu));
683 MidiTimeAxisView::build_note_mode_menu()
685 using namespace Menu_Helpers;
687 Menu* mode_menu = manage (new Menu);
688 MenuList& items = mode_menu->items();
689 mode_menu->set_name ("ArdourContextMenu");
691 RadioMenuItem::Group mode_group;
692 items.push_back (RadioMenuElem (mode_group, _("Sustained"),
693 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_note_mode), Sustained)));
694 _note_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
695 _note_mode_item->set_active(_note_mode == Sustained);
697 items.push_back (RadioMenuElem (mode_group, _("Percussive"),
698 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_note_mode), Percussive)));
699 _percussion_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
700 _percussion_mode_item->set_active(_note_mode == Percussive);
706 MidiTimeAxisView::build_color_mode_menu()
708 using namespace Menu_Helpers;
710 Menu* mode_menu = manage (new Menu);
711 MenuList& items = mode_menu->items();
712 mode_menu->set_name ("ArdourContextMenu");
714 RadioMenuItem::Group mode_group;
715 items.push_back (RadioMenuElem (mode_group, _("Meter Colors"),
716 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_color_mode), MeterColors)));
717 _meter_color_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
718 _meter_color_mode_item->set_active(_color_mode == MeterColors);
720 items.push_back (RadioMenuElem (mode_group, _("Channel Colors"),
721 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_color_mode), ChannelColors)));
722 _channel_color_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
723 _channel_color_mode_item->set_active(_color_mode == ChannelColors);
725 items.push_back (RadioMenuElem (mode_group, _("Track Color"),
726 sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_color_mode), TrackColor)));
727 _channel_color_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
728 _channel_color_mode_item->set_active(_color_mode == TrackColor);
734 MidiTimeAxisView::set_note_mode(NoteMode mode)
736 if (_note_mode != mode || midi_track()->note_mode() != mode) {
738 midi_track()->set_note_mode(mode);
739 xml_node->add_property ("note-mode", enum_2_string(_note_mode));
740 _view->redisplay_diskstream();
745 MidiTimeAxisView::set_color_mode(ColorMode mode)
747 if (_color_mode != mode) {
748 if (mode == ChannelColors) {
749 _channel_selector.set_channel_colors(CanvasNoteEvent::midi_channel_colors);
751 _channel_selector.set_default_channel_color();
755 xml_node->add_property ("color-mode", enum_2_string(_color_mode));
756 _view->redisplay_diskstream();
761 MidiTimeAxisView::set_note_range(MidiStreamView::VisibleNoteRange range)
763 if (!_ignore_signals)
764 midi_view()->set_note_range(range);
769 MidiTimeAxisView::update_range()
771 MidiGhostRegion* mgr;
773 for(list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
774 if ((mgr = dynamic_cast<MidiGhostRegion*>(*i)) != 0) {
781 MidiTimeAxisView::show_all_automation ()
784 const set<Evoral::Parameter> params = midi_track()->midi_diskstream()->
785 midi_playlist()->contained_automation();
787 for (set<Evoral::Parameter>::const_iterator i = params.begin(); i != params.end(); ++i) {
788 create_automation_child(*i, true);
792 RouteTimeAxisView::show_all_automation ();
796 MidiTimeAxisView::show_existing_automation ()
799 const set<Evoral::Parameter> params = midi_track()->midi_diskstream()->
800 midi_playlist()->contained_automation();
802 for (set<Evoral::Parameter>::const_iterator i = params.begin(); i != params.end(); ++i) {
803 create_automation_child(*i, true);
807 RouteTimeAxisView::show_existing_automation ();
810 /** Hide an automation track for the given parameter (pitch bend, channel pressure).
813 MidiTimeAxisView::create_automation_child (const Evoral::Parameter& param, bool show)
815 /* These controllers are region "automation", so we do not create
816 * an AutomationList/Line for the track */
818 if (param.type() == NullAutomation) {
819 cerr << "WARNING: Attempt to create NullAutomation child, ignoring" << endl;
823 AutomationTracks::iterator existing = _automation_tracks.find (param);
824 if (existing != _automation_tracks.end()) {
828 boost::shared_ptr<AutomationControl> c = _route->get_control (param);
832 boost::shared_ptr<AutomationTimeAxisView> track(new AutomationTimeAxisView (_session,
833 _route, boost::shared_ptr<ARDOUR::Automatable>(), c,
838 _route->describe_parameter(param)));
840 add_automation_child (param, track, show);
845 MidiTimeAxisView::route_active_changed ()
847 RouteUI::route_active_changed ();
850 if (_route->active()) {
851 controls_ebox.set_name ("MidiTrackControlsBaseUnselected");
852 controls_base_selected_name = "MidiTrackControlsBaseSelected";
853 controls_base_unselected_name = "MidiTrackControlsBaseUnselected";
855 controls_ebox.set_name ("MidiTrackControlsBaseInactiveUnselected");
856 controls_base_selected_name = "MidiTrackControlsBaseInactiveSelected";
857 controls_base_unselected_name = "MidiTrackControlsBaseInactiveUnselected";
863 if (_route->active()) {
864 controls_ebox.set_name ("BusControlsBaseUnselected");
865 controls_base_selected_name = "BusControlsBaseSelected";
866 controls_base_unselected_name = "BusControlsBaseUnselected";
868 controls_ebox.set_name ("BusControlsBaseInactiveUnselected");
869 controls_base_selected_name = "BusControlsBaseInactiveSelected";
870 controls_base_unselected_name = "BusControlsBaseInactiveUnselected";
876 MidiTimeAxisView::start_step_editing ()
878 step_edit_insert_position = _editor.get_preferred_edit_position ();
879 step_edit_beat_pos = 0;
880 step_edit_region = playlist()->top_region_at (step_edit_insert_position);
882 if (step_edit_region) {
883 RegionView* rv = view()->find_view (step_edit_region);
884 step_edit_region_view = dynamic_cast<MidiRegionView*> (rv);
886 step_edit_region_view = 0;
889 midi_track()->set_step_editing (true);
893 MidiTimeAxisView::stop_step_editing ()
895 midi_track()->set_step_editing (false);
899 MidiTimeAxisView::check_step_edit ()
901 MidiRingBuffer<nframes_t>& incoming (midi_track()->step_edit_ring_buffer());
902 Evoral::Note<Evoral::MusicalTime> note;
904 uint32_t bufsize = 32;
906 buf = new uint8_t[bufsize];
908 while (incoming.read_space()) {
910 Evoral::EventType type;
913 incoming.read_prefix (&time, &type, &size);
915 if (size > bufsize) {
918 buf = new uint8_t[bufsize];
921 incoming.read_contents (size, buf);
923 if ((buf[0] & 0xf0) == MIDI_CMD_NOTE_ON) {
925 if (step_edit_region == 0) {
927 step_edit_region = add_region (step_edit_insert_position);
928 RegionView* rv = view()->find_view (step_edit_region);
931 step_edit_region_view = dynamic_cast<MidiRegionView*>(rv);
933 fatal << X_("programming error: no view found for new MIDI region") << endmsg;
938 if (step_edit_region_view) {
941 Evoral::MusicalTime beats = _editor.get_grid_type_as_beats (success, step_edit_insert_position);
947 step_edit_region_view->add_note (buf[0] & 0xf, buf[1], buf[2], step_edit_beat_pos, beats);
948 step_edit_beat_pos += beats;
956 MidiTimeAxisView::step_edit_rest ()
959 Evoral::MusicalTime beats = _editor.get_grid_type_as_beats (success, step_edit_insert_position);
960 step_edit_beat_pos += beats;
963 boost::shared_ptr<Region>
964 MidiTimeAxisView::add_region (nframes64_t pos)
966 Editor* real_editor = dynamic_cast<Editor*> (&_editor);
968 real_editor->begin_reversible_command (_("create region"));
969 XMLNode &before = playlist()->get_state();
971 nframes64_t start = pos;
972 real_editor->snap_to (start, -1);
973 const Meter& m = _session->tempo_map().meter_at(start);
974 const Tempo& t = _session->tempo_map().tempo_at(start);
975 double length = floor (m.frames_per_bar(t, _session->frame_rate()));
977 const boost::shared_ptr<MidiDiskstream> diskstream =
978 boost::dynamic_pointer_cast<MidiDiskstream>(view()->trackview().track()->diskstream());
980 boost::shared_ptr<Source> src = _session->create_midi_source_for_session (*diskstream.get());
982 boost::shared_ptr<Region> region = (RegionFactory::create (src, 0, (nframes_t) length,
983 PBD::basename_nosuffix(src->name())));
985 playlist()->add_region (region, start);
986 XMLNode &after = playlist()->get_state();
987 _session->add_command (new MementoCommand<Playlist> (*playlist().get(), &before, &after));
989 real_editor->commit_reversible_command();
995 MidiTimeAxisView::add_note_selection (uint8_t note)
997 if (!_editor.internal_editing()) {
1001 uint16_t chn_mask = _channel_selector.get_selected_channels();
1003 if (_view->num_selected_regionviews() == 0) {
1004 _view->foreach_regionview (sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::add_note_selection_region_view), note, chn_mask));
1006 _view->foreach_selected_regionview (sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::add_note_selection_region_view), note, chn_mask));
1011 MidiTimeAxisView::extend_note_selection (uint8_t note)
1013 if (!_editor.internal_editing()) {
1017 uint16_t chn_mask = _channel_selector.get_selected_channels();
1019 if (_view->num_selected_regionviews() == 0) {
1020 _view->foreach_regionview (sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::extend_note_selection_region_view), note, chn_mask));
1022 _view->foreach_selected_regionview (sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::extend_note_selection_region_view), note, chn_mask));
1027 MidiTimeAxisView::toggle_note_selection (uint8_t note)
1029 if (!_editor.internal_editing()) {
1033 uint16_t chn_mask = _channel_selector.get_selected_channels();
1035 if (_view->num_selected_regionviews() == 0) {
1036 _view->foreach_regionview (sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_note_selection_region_view), note, chn_mask));
1038 _view->foreach_selected_regionview (sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_note_selection_region_view), note, chn_mask));
1043 MidiTimeAxisView::add_note_selection_region_view (RegionView* rv, uint8_t note, uint16_t chn_mask)
1045 dynamic_cast<MidiRegionView*>(rv)->select_matching_notes (note, chn_mask, false, false);
1049 MidiTimeAxisView::extend_note_selection_region_view (RegionView* rv, uint8_t note, uint16_t chn_mask)
1051 dynamic_cast<MidiRegionView*>(rv)->select_matching_notes (note, chn_mask, true, true);
1055 MidiTimeAxisView::toggle_note_selection_region_view (RegionView* rv, uint8_t note, uint16_t chn_mask)
1057 dynamic_cast<MidiRegionView*>(rv)->toggle_matching_notes (note, chn_mask);
1061 MidiTimeAxisView::set_channel_mode (ChannelMode, uint16_t)
1063 /* invalidate the controller menu, so that we rebuilt it next time */
1064 delete controller_menu;
1065 controller_menu = 0;