summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-07-15 01:56:11 +0000
committerDavid Robillard <d@drobilla.net>2007-07-15 01:56:11 +0000
commit332a3d98138e94903ad9c6d35048b0201ff178c8 (patch)
tree107ac2a68b8c461a534e82d41e47fedfc5ed9178 /gtk2_ardour
parent74eded425a5244831c80968c1781c3f81f90e996 (diff)
Selection of visible note range (full range vs fit contents, selectable from midi track menu).
Added note pencil tool, mock note adding (notes can be added visually but don't yet play). Reworked MidiModel to be notes w/ duration instead of realtime style MIDI events. Moved layering (stacked/overlaid) from auto time axis down to route time axis since it applies to MIDI tracks as well. git-svn-id: svn://localhost/ardour2/trunk@2128 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/audio_time_axis.cc19
-rw-r--r--gtk2_ardour/audio_time_axis.h1
-rw-r--r--gtk2_ardour/editing_syms.h1
-rw-r--r--gtk2_ardour/editor.cc12
-rw-r--r--gtk2_ardour/editor.h2
-rw-r--r--gtk2_ardour/editor_actions.cc1
-rw-r--r--gtk2_ardour/editor_mouse.cc16
-rw-r--r--gtk2_ardour/midi_region_view.cc114
-rw-r--r--gtk2_ardour/midi_region_view.h4
-rw-r--r--gtk2_ardour/midi_streamview.cc27
-rw-r--r--gtk2_ardour/midi_streamview.h19
-rw-r--r--gtk2_ardour/midi_time_axis.cc37
-rw-r--r--gtk2_ardour/midi_time_axis.h5
-rw-r--r--gtk2_ardour/route_time_axis.cc30
-rw-r--r--gtk2_ardour/route_time_axis.h1
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);