diff options
Diffstat (limited to 'gtk2_ardour')
-rw-r--r-- | gtk2_ardour/audio_time_axis.cc | 19 | ||||
-rw-r--r-- | gtk2_ardour/audio_time_axis.h | 1 | ||||
-rw-r--r-- | gtk2_ardour/editing_syms.h | 1 | ||||
-rw-r--r-- | gtk2_ardour/editor.cc | 12 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor_actions.cc | 1 | ||||
-rw-r--r-- | gtk2_ardour/editor_mouse.cc | 16 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 114 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.h | 4 | ||||
-rw-r--r-- | gtk2_ardour/midi_streamview.cc | 27 | ||||
-rw-r--r-- | gtk2_ardour/midi_streamview.h | 19 | ||||
-rw-r--r-- | gtk2_ardour/midi_time_axis.cc | 37 | ||||
-rw-r--r-- | gtk2_ardour/midi_time_axis.h | 5 | ||||
-rw-r--r-- | gtk2_ardour/route_time_axis.cc | 30 | ||||
-rw-r--r-- | gtk2_ardour/route_time_axis.h | 1 |
15 files changed, 243 insertions, 46 deletions
diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc index db88982089..437e037836 100644 --- a/gtk2_ardour/audio_time_axis.cc +++ b/gtk2_ardour/audio_time_axis.cc @@ -206,17 +206,6 @@ AudioTimeAxisView::append_extra_display_menu_items () items.push_back (MenuElem (_("Waveform"), *waveform_menu)); - - Menu *layers_menu = manage(new Menu); - MenuList &layers_items = layers_menu->items(); - layers_menu->set_name("ArdourContextMenu"); - - RadioMenuItem::Group layers_group; - - layers_items.push_back(RadioMenuElem (layers_group, _("Overlaid"), bind (mem_fun (*this, &AudioTimeAxisView::set_layer_display), Overlaid))); - layers_items.push_back(RadioMenuElem (layers_group, _("Stacked"), bind (mem_fun (*this, &AudioTimeAxisView::set_layer_display), Stacked))); - - items.push_back (MenuElem (_("Layers"), *layers_menu)); } Gtk::Menu* @@ -487,11 +476,3 @@ AudioTimeAxisView::update_control_names () } } -void -AudioTimeAxisView::set_layer_display (LayerDisplay d) -{ - AudioStreamView* asv = audio_view (); - if (asv) { - asv->set_layer_display (d); - } -} diff --git a/gtk2_ardour/audio_time_axis.h b/gtk2_ardour/audio_time_axis.h index 822fbcadf0..a65bca1a70 100644 --- a/gtk2_ardour/audio_time_axis.h +++ b/gtk2_ardour/audio_time_axis.h @@ -76,7 +76,6 @@ class AudioTimeAxisView : public RouteTimeAxisView void hide_all_xfades (); void hide_dependent_views (TimeAxisViewItem&); void reveal_dependent_views (TimeAxisViewItem&); - void set_layer_display (LayerDisplay d); /* Overridden from parent to store display state */ guint32 show_at (double y, int& nth, Gtk::VBox *parent); diff --git a/gtk2_ardour/editing_syms.h b/gtk2_ardour/editing_syms.h index f415e2c49c..7ae45c4c06 100644 --- a/gtk2_ardour/editing_syms.h +++ b/gtk2_ardour/editing_syms.h @@ -60,6 +60,7 @@ MOUSEMODE(MouseRange) MOUSEMODE(MouseTimeFX) MOUSEMODE(MouseZoom) MOUSEMODE(MouseAudition) +MOUSEMODE(MouseNote) /* Changing this order will break the menu */ ZOOMFOCUS(ZoomFocusLeft) diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index a771fb51b4..cd1b9e4b7c 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -152,6 +152,7 @@ Gdk::Cursor* Editor::zoom_cursor = 0; Gdk::Cursor* Editor::time_fx_cursor = 0; Gdk::Cursor* Editor::fader_cursor = 0; Gdk::Cursor* Editor::speaker_cursor = 0; +Gdk::Cursor* Editor::note_cursor = 0; Gdk::Cursor* Editor::wait_cursor = 0; Gdk::Cursor* Editor::timebar_cursor = 0; @@ -1210,7 +1211,7 @@ Editor::build_cursors () mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height); speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot); } - + grabber_cursor = new Gdk::Cursor (HAND2); cross_hair_cursor = new Gdk::Cursor (CROSSHAIR); trimmer_cursor = new Gdk::Cursor (SB_H_DOUBLE_ARROW); @@ -1218,6 +1219,7 @@ Editor::build_cursors () time_fx_cursor = new Gdk::Cursor (SIZING); wait_cursor = new Gdk::Cursor (WATCH); timebar_cursor = new Gdk::Cursor(LEFT_PTR); + note_cursor = new Gdk::Cursor (PENCIL); } /** Pop up a context menu for when the user clicks on a fade in or fade out */ @@ -2322,6 +2324,9 @@ Editor::setup_toolbar () mouse_mode_buttons.push_back (&mouse_timefx_button); mouse_audition_button.add (*(manage (new Image (::get_icon("tool_audition"))))); mouse_audition_button.set_relief(Gtk::RELIEF_NONE); + mouse_note_button.add (*(manage (new Image (::get_icon("tool_note"))))); + mouse_note_button.set_relief(Gtk::RELIEF_NONE); + mouse_mode_buttons.push_back (&mouse_note_button); mouse_mode_buttons.push_back (&mouse_audition_button); mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons); @@ -2336,6 +2341,7 @@ Editor::setup_toolbar () mouse_mode_button_box.pack_start(mouse_gain_button, true, true); mouse_mode_button_box.pack_start(mouse_timefx_button, true, true); mouse_mode_button_box.pack_start(mouse_audition_button, true, true); + mouse_mode_button_box.pack_start(mouse_note_button, true, true); mouse_mode_button_box.set_homogeneous(true); vector<string> edit_mode_strings; @@ -2368,6 +2374,7 @@ Editor::setup_toolbar () mouse_zoom_button.set_name ("MouseModeButton"); mouse_timefx_button.set_name ("MouseModeButton"); mouse_audition_button.set_name ("MouseModeButton"); + mouse_note_button.set_name ("MouseModeButton"); ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("Select/Move Objects")); ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("Select/Move Ranges")); @@ -2375,6 +2382,7 @@ Editor::setup_toolbar () ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("Select Zoom Range")); ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("Stretch/Shrink Regions")); ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("Listen to Specific Regions")); + ARDOUR_UI::instance()->tooltips().set_tip (mouse_note_button, _("Edit MIDI Notes")); mouse_move_button.unset_flags (CAN_FOCUS); mouse_select_button.unset_flags (CAN_FOCUS); @@ -2382,6 +2390,7 @@ Editor::setup_toolbar () mouse_zoom_button.unset_flags (CAN_FOCUS); mouse_timefx_button.unset_flags (CAN_FOCUS); mouse_audition_button.unset_flags (CAN_FOCUS); + mouse_note_button.unset_flags (CAN_FOCUS); mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange)); mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release)); @@ -2391,6 +2400,7 @@ Editor::setup_toolbar () mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom)); mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX)); mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition)); + mouse_note_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseNote)); // mouse_move_button.set_active (true); diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index b9a4f29cec..b4c0a03f85 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -808,6 +808,7 @@ class Editor : public PublicEditor static Gdk::Cursor* time_fx_cursor; static Gdk::Cursor* fader_cursor; static Gdk::Cursor* speaker_cursor; + static Gdk::Cursor* note_cursor; static Gdk::Cursor* wait_cursor; static Gdk::Cursor* timebar_cursor; @@ -1317,6 +1318,7 @@ class Editor : public PublicEditor Gtk::ToggleButton mouse_zoom_button; Gtk::ToggleButton mouse_timefx_button; Gtk::ToggleButton mouse_audition_button; + Gtk::ToggleButton mouse_note_button; GroupedButtons *mouse_mode_button_set; void mouse_mode_toggled (Editing::MouseMode m); bool ignore_mouse_mode_toggle; diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 52f30e7d5d..585c4669e2 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -301,6 +301,7 @@ Editor::register_actions () ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-gain", _("Gain Tool"), bind (mem_fun(*this, &Editor::set_mouse_mode), Editing::MouseGain, false)); ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-zoom", _("Zoom Tool"), bind (mem_fun(*this, &Editor::set_mouse_mode), Editing::MouseZoom, false)); ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-timefx", _("Timefx Tool"), bind (mem_fun(*this, &Editor::set_mouse_mode), Editing::MouseTimeFX, false)); + ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-note", _("Note Tool"), bind (mem_fun(*this, &Editor::set_mouse_mode), Editing::MouseNote, false)); ActionManager::register_action (editor_actions, X_("SnapTo"), _("Snap To")); ActionManager::register_action (editor_actions, X_("SnapMode"), _("Snap Mode")); diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 406eda01db..be2d0bc47d 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -160,6 +160,12 @@ Editor::mouse_mode_toggled (MouseMode m) set_mouse_mode (m); } break; + + case MouseNote: + if (mouse_note_button.get_active()) { + set_mouse_mode (m); + } + break; default: break; @@ -244,6 +250,11 @@ Editor::set_mouse_mode (MouseMode m, bool force) mouse_audition_button.set_active (true); current_canvas_cursor = speaker_cursor; break; + + case MouseNote: + mouse_note_button.set_active (true); + current_canvas_cursor = note_cursor; + break; } ignore_mouse_mode_toggle = false; @@ -286,6 +297,11 @@ Editor::step_mouse_mode (bool next) if (next) set_mouse_mode (MouseObject); else set_mouse_mode (MouseTimeFX); break; + + case MouseNote: + if (next) set_mouse_mode (MouseObject); + else set_mouse_mode (MouseAudition); + break; } } diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index e4cb80bca0..81ea4029de 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -25,10 +25,12 @@ #include <gtkmm2ext/gtk_ui.h> #include <ardour/playlist.h> +#include <ardour/tempo.h> #include <ardour/midi_region.h> #include <ardour/midi_source.h> #include <ardour/midi_diskstream.h> #include <ardour/midi_events.h> +#include <ardour/midi_model.h> #include "streamview.h" #include "midi_region_view.h" @@ -93,6 +95,52 @@ MidiRegionView::init (Gdk::Color& basic_color, bool wfd) midi_region()->midi_source(0)->load_model(); display_events(); } + + group->signal_event().connect (mem_fun (this, &MidiRegionView::canvas_event)); +} + +bool +MidiRegionView::canvas_event(GdkEvent* ev) +{ + if (trackview.editor.current_mouse_mode() == MouseNote) { + if (ev->type == GDK_BUTTON_PRESS) { + MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview); + MidiStreamView* const view = mtv->midi_view(); + + const uint8_t note_range = view->highest_note() - view->lowest_note() + 1; + const double footer_height = name_highlight->property_y2() - name_highlight->property_y1(); + const double roll_height = trackview.height - footer_height; + + double x = ev->button.x; + double y = ev->button.y; + get_canvas_group()->w2i(x, y); + + double note = floor((roll_height - y) / roll_height * (double)note_range) + view->lowest_note(); + assert(note >= 0.0); + assert(note <= 127.0); + + const nframes_t stamp = trackview.editor.pixel_to_frame (x); + assert(stamp >= 0); + //assert(stamp <= _region->length()); + + const Meter& m = trackview.session().tempo_map().meter_at(stamp); + const Tempo& t = trackview.session().tempo_map().tempo_at(stamp); + double dur = m.frames_per_bar(t, trackview.session().frame_rate()) / m.beats_per_bar(); + + // Add a 1 beat long note (for now) + const MidiModel::Note new_note(stamp, dur, (uint8_t)note, 0x40); + + MidiModel::Notes& notes = midi_region()->midi_source(0)->model()->notes(); + MidiModel::Notes::iterator i = upper_bound(notes.begin(), notes.end(), new_note, + MidiModel::NoteTimeComparator()); + notes.insert(i, new_note); + view->update_bounds(new_note.note); + + add_note(new_note); + } + } + + return false; } @@ -113,8 +161,8 @@ MidiRegionView::display_events() begin_write(); - for (size_t i=0; i < midi_region()->midi_source(0)->model()->n_events(); ++i) - add_event(midi_region()->midi_source(0)->model()->event_at(i)); + for (size_t i=0; i < midi_region()->midi_source(0)->model()->n_notes(); ++i) + add_note(midi_region()->midi_source(0)->model()->note_at(i)); end_write(); } @@ -222,6 +270,11 @@ MidiRegionView::end_write() } +/** Add a MIDI event. + * + * This is used while recording, and handles displaying still-unresolved notes. + * Displaying an existing model is simpler, and done with add_note. + */ void MidiRegionView::add_event (const MidiEvent& ev) { @@ -300,4 +353,61 @@ MidiRegionView::extend_active_notes() } +/** Add a MIDI note (with duration). + * + * This does no 'realtime' note resolution, notes from a MidiModel have a + * duration so they can be drawn in full immediately. + */ +void +MidiRegionView::add_note (const MidiModel::Note& note) +{ + assert(note.start >= 0); + assert(note.start < _region->length()); + //assert(note.start + note.duration < _region->length()); + + /*printf("Event, time = %f, size = %zu, data = ", ev.time, ev.size); + for (size_t i=0; i < ev.size; ++i) { + printf("%X ", ev.buffer[i]); + } + printf("\n\n");*/ + + MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview); + MidiStreamView* const view = mtv->midi_view(); + ArdourCanvas::Group* const group = (ArdourCanvas::Group*)get_canvas_group(); + + const uint8_t note_range = view->highest_note() - view->lowest_note() + 1; + const double footer_height = name_highlight->property_y2() - name_highlight->property_y1(); + const double pixel_range = (trackview.height - footer_height - 5.0) / (double)note_range; + + if (mtv->note_mode() == Note) { + const double y1 = trackview.height - (pixel_range * (note.note - view->lowest_note() + 1)) + - footer_height - 3.0; + + ArdourCanvas::SimpleRect * ev_rect = new Gnome::Canvas::SimpleRect(*group); + ev_rect->property_x1() = trackview.editor.frame_to_pixel((nframes_t)note.start); + ev_rect->property_y1() = y1; + ev_rect->property_x2() = trackview.editor.frame_to_pixel((nframes_t)(note.start + note.duration)); + ev_rect->property_y2() = y1 + ceil(pixel_range); + + ev_rect->property_fill_color_rgba() = 0xFFFFFF66; + ev_rect->property_outline_color_rgba() = 0xFFFFFFAA; + ev_rect->property_outline_what() = (guint32) 0xF; // all edges + + ev_rect->show(); + _events.push_back(ev_rect); + + } else if (mtv->note_mode() == Percussion) { + const double x = trackview.editor.frame_to_pixel((nframes_t)note.start); + const double y = trackview.height - (pixel_range * (note.note - view->lowest_note() + 1)) + - footer_height - 3.0; + + Diamond* ev_diamond = new Diamond(*group, std::min(pixel_range, 5.0)); + ev_diamond->move(x, y); + ev_diamond->show(); + ev_diamond->property_outline_color_rgba() = 0xFFFFFFDD; + ev_diamond->property_fill_color_rgba() = 0xFFFFFF66; + _events.push_back(ev_diamond); + } +} + diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 88ef43243b..6e37da9f50 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -25,6 +25,7 @@ #include <libgnomecanvasmm/polygon.h> #include <sigc++/signal.h> #include <ardour/midi_region.h> +#include <ardour/midi_model.h> #include <ardour/types.h> #include "region_view.h" @@ -64,6 +65,7 @@ class MidiRegionView : public RegionView GhostRegion* add_ghost (AutomationTimeAxisView&); void add_event(const ARDOUR::MidiEvent& ev); + void add_note(const ARDOUR::MidiModel::Note& note); void begin_write(); void end_write(); @@ -95,6 +97,8 @@ class MidiRegionView : public RegionView void display_events(); void clear_events(); + bool canvas_event(GdkEvent* ev); + std::vector<ArdourCanvas::Item*> _events; ArdourCanvas::SimpleRect** _active_notes; }; diff --git a/gtk2_ardour/midi_streamview.cc b/gtk2_ardour/midi_streamview.cc index 862e554cae..30700c8e94 100644 --- a/gtk2_ardour/midi_streamview.cc +++ b/gtk2_ardour/midi_streamview.cc @@ -54,8 +54,8 @@ using namespace Editing; MidiStreamView::MidiStreamView (MidiTimeAxisView& tv) : StreamView (tv) - , _lowest_note(0) - , _highest_note(127) + , _lowest_note(60) + , _highest_note(60) { if (tv.is_track()) stream_base_color = ARDOUR_UI::config()->canvasvar_MidiTrackBase.get(); @@ -137,17 +137,13 @@ MidiStreamView::display_region(MidiRegionView* region_view, bool redisplay_event boost::shared_ptr<MidiSource> source(region_view->midi_region()->midi_source(0)); - for (size_t i=0; i < source->model()->n_events(); ++i) { - const MidiEvent& ev = source->model()->event_at(i); + for (size_t i=0; i < source->model()->n_notes(); ++i) { + const MidiModel::Note& note = source->model()->note_at(i); - // Look at all note on events to find our note range - if ((ev.buffer[0] & 0xF0) == MIDI_CMD_NOTE_ON) { - _lowest_note = min(_lowest_note, ev.buffer[1]); - _highest_note = max(_highest_note, ev.buffer[1]); - } + update_bounds(note.note); if (redisplay_events) - region_view->add_event(ev); + region_view->add_note(note); } if (redisplay_events) @@ -164,8 +160,8 @@ MidiStreamView::redisplay_diskstream () (*i)->set_valid (false); } - _lowest_note = 60; // middle C - _highest_note = _lowest_note + 11; + //_lowest_note = 60; // middle C + //_highest_note = _lowest_note + 11; if (_trackview.is_midi_track()) { _trackview.get_diskstream()->playlist()->foreach_region (static_cast<StreamView*>(this), &StreamView::add_region_view); @@ -191,6 +187,13 @@ MidiStreamView::redisplay_diskstream () region_layered (*i); } } + +void +MidiStreamView::update_bounds(uint8_t note_num) +{ + _lowest_note = min(_lowest_note, note_num); + _highest_note = max(_highest_note, note_num); +} void diff --git a/gtk2_ardour/midi_streamview.h b/gtk2_ardour/midi_streamview.h index ce459e2fad..b8ae33cf46 100644 --- a/gtk2_ardour/midi_streamview.h +++ b/gtk2_ardour/midi_streamview.h @@ -58,8 +58,18 @@ class MidiStreamView : public StreamView void get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable* >&); void get_inverted_selectables (Selection&, list<Selectable* >& results); - uint8_t lowest_note() const { return _lowest_note; } - uint8_t highest_note() const { return _highest_note; } + enum VisibleNoteRange { + FullRange, + ContentsRange + }; + + VisibleNoteRange note_range() { return _range; } + void set_note_range(VisibleNoteRange r) { _range = r; } + + uint8_t lowest_note() const { return (_range == FullRange) ? 0 : _lowest_note; } + uint8_t highest_note() const { return (_range == FullRange) ? 127 : _highest_note; } + + void update_bounds(uint8_t note_num); void redisplay_diskstream (); @@ -73,8 +83,9 @@ class MidiStreamView : public StreamView void color_handler (); - uint8_t _lowest_note; - uint8_t _highest_note; + VisibleNoteRange _range; + uint8_t _lowest_note; + uint8_t _highest_note; }; #endif /* __ardour_midi_streamview_h__ */ diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index 48aa78dc06..fb3d67913d 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -157,6 +157,31 @@ MidiTimeAxisView::hide () } void +MidiTimeAxisView::append_extra_display_menu_items () +{ + using namespace Menu_Helpers; + + MenuList& items = display_menu->items(); + + // Note range + Menu *range_menu = manage(new Menu); + MenuList& range_items = range_menu->items(); + range_menu->set_name ("ArdourContextMenu"); + + RadioMenuItem::Group range_group; + + range_items.push_back (RadioMenuElem (range_group, _("Show Full Range"), bind ( + mem_fun(*this, &MidiTimeAxisView::set_note_range), + MidiStreamView::FullRange))); + + range_items.push_back (RadioMenuElem (range_group, _("Fit Contents"), bind ( + mem_fun(*this, &MidiTimeAxisView::set_note_range), + MidiStreamView::ContentsRange))); + + items.push_back (MenuElem (_("Note range"), *range_menu)); +} + +void MidiTimeAxisView::build_automation_action_menu () { using namespace Menu_Helpers; @@ -204,6 +229,17 @@ MidiTimeAxisView::set_note_mode(NoteMode mode) } } + +void +MidiTimeAxisView::set_note_range(MidiStreamView::VisibleNoteRange range) +{ + //if (midi_view()->note_range() != range) { + midi_view()->set_note_range(range); + midi_view()->redisplay_diskstream(); + //} +} + + /** Prompt for a controller with a dialog and add an automation track for it */ void @@ -285,3 +321,4 @@ MidiTimeAxisView::route_active_changed () } } + diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h index 039affd979..a35a332e01 100644 --- a/gtk2_ardour/midi_time_axis.h +++ b/gtk2_ardour/midi_time_axis.h @@ -38,6 +38,7 @@ #include "enums.h" #include "route_time_axis.h" #include "canvas.h" +#include "midi_streamview.h" namespace ARDOUR { class Session; @@ -67,13 +68,15 @@ class MidiTimeAxisView : public RouteTimeAxisView void create_automation_child (ARDOUR::Parameter param, bool show); ARDOUR::NoteMode note_mode() const { return _note_mode; } - + private: + void append_extra_display_menu_items (); void build_automation_action_menu (); Gtk::Menu* build_mode_menu(); void set_note_mode(ARDOUR::NoteMode mode); + void set_note_range(MidiStreamView::VisibleNoteRange range); void route_active_changed (); diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index e0d93bd41a..dbfb8b029b 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -500,29 +500,42 @@ RouteTimeAxisView::build_display_menu () if (is_track()) { + Menu *layers_menu = manage(new Menu); + MenuList &layers_items = layers_menu->items(); + layers_menu->set_name("ArdourContextMenu"); + + RadioMenuItem::Group layers_group; + + layers_items.push_back(RadioMenuElem (layers_group, _("Overlaid"), + bind (mem_fun (*this, &RouteTimeAxisView::set_layer_display), Overlaid))); + layers_items.push_back(RadioMenuElem (layers_group, _("Stacked"), + bind (mem_fun (*this, &RouteTimeAxisView::set_layer_display), Stacked))); + + items.push_back (MenuElem (_("Layers"), *layers_menu)); + Menu* alignment_menu = manage (new Menu); MenuList& alignment_items = alignment_menu->items(); alignment_menu->set_name ("ArdourContextMenu"); RadioMenuItem::Group align_group; - + alignment_items.push_back (RadioMenuElem (align_group, _("Align with existing material"), - bind (mem_fun(*this, &RouteTimeAxisView::set_align_style), ExistingMaterial))); + bind (mem_fun(*this, &RouteTimeAxisView::set_align_style), ExistingMaterial))); align_existing_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back()); if (get_diskstream()->alignment_style() == ExistingMaterial) align_existing_item->set_active(); - + alignment_items.push_back (RadioMenuElem (align_group, _("Align with capture time"), - bind (mem_fun(*this, &RouteTimeAxisView::set_align_style), CaptureTime))); + bind (mem_fun(*this, &RouteTimeAxisView::set_align_style), CaptureTime))); align_capture_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back()); if (get_diskstream()->alignment_style() == CaptureTime) align_capture_item->set_active(); - + items.push_back (MenuElem (_("Alignment"), *alignment_menu)); get_diskstream()->AlignmentStyleChanged.connect ( mem_fun(*this, &RouteTimeAxisView::align_style_changed)); - + mode_menu = build_mode_menu(); if (mode_menu) items.push_back (MenuElem (_("Mode"), *mode_menu)); @@ -1980,3 +1993,8 @@ RouteTimeAxisView::update_rec_display () name_entry.set_sensitive (!_route->record_enabled()); } +void +RouteTimeAxisView::set_layer_display (LayerDisplay d) +{ + _view->set_layer_display (d); +} diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h index 0d42f331a9..cd92f47322 100644 --- a/gtk2_ardour/route_time_axis.h +++ b/gtk2_ardour/route_time_axis.h @@ -79,6 +79,7 @@ public: void get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable *>&); void get_inverted_selectables (Selection&, list<Selectable*>&); bool show_automation(ARDOUR::Parameter param); + void set_layer_display (LayerDisplay d); boost::shared_ptr<ARDOUR::Region> find_next_region (nframes_t pos, ARDOUR::RegionPoint, int32_t dir); |