#include "gui_thread.h"
#include "utils.h"
#include "simplerect.h"
+#include "simpleline.h"
using namespace std;
using namespace ARDOUR;
MidiStreamView::MidiStreamView (MidiTimeAxisView& tv)
: StreamView (tv)
- , _lowest_note(0)
- , _highest_note(127)
+ , _range(ContentsRange)
+ , _lowest_note(60)
+ , _highest_note(71)
{
if (tv.is_track())
stream_base_color = ARDOUR_UI::config()->canvasvar_MidiTrackBase.get();
canvas_rect->property_fill_color_rgba() = stream_base_color;
canvas_rect->property_outline_color_rgba() = RGBA_BLACK;
- //use_rec_regions = tv.editor.show_waveforms_recording ();
- use_rec_regions = true;
+ use_rec_regions = tv.editor.show_waveforms_recording ();
+
+ _note_line_group = new ArdourCanvas::Group (*canvas_group);
+
+ for (uint8_t i=0; i < 127; ++i) {
+ _note_lines[i] = new ArdourCanvas::SimpleLine(*_note_line_group,
+ 0, note_to_y(i), 10, note_to_y(i));
+ _note_lines[i]->property_color_rgba() = 0xEEEEEE55;
+ }
}
MidiStreamView::~MidiStreamView ()
RegionView*
-MidiStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wait_for_waves)
+MidiStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wfd)
{
boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion> (r);
/* great. we already have a MidiRegionView for this Region. use it again. */
(*i)->set_valid (true);
- display_region(dynamic_cast<MidiRegionView*>(*i), false);
+ (*i)->enable_display(wfd);
+ display_region(dynamic_cast<MidiRegionView*>(*i), wfd);
return NULL;
}
}
- // can't we all just get along?
- assert(_trackview.midi_track()->mode() != Destructive);
-
region_view = new MidiRegionView (canvas_group, _trackview, region,
_samples_per_unit, region_color);
-
- region_view->init (region_color, wait_for_waves);
+
+ region_view->init (region_color, false);
region_views.push_front (region_view);
/* follow global waveform setting */
- // FIXME
- //region_view->set_waveform_visible(_trackview.editor.show_waveforms());
+ if (wfd) {
+ region_view->enable_display(true);
+ region_view->midi_region()->midi_source(0)->load_model();
+ }
/* display events and find note range */
- display_region(region_view, false);
+ display_region(region_view, wfd);
/* always display at least 1 octave range */
_highest_note = max(_highest_note, static_cast<uint8_t>(_lowest_note + 11));
}
void
-MidiStreamView::display_region(MidiRegionView* region_view, bool redisplay_events)
+MidiStreamView::display_region(MidiRegionView* region_view, bool load_model)
{
if ( ! region_view)
return;
- if (redisplay_events)
- region_view->begin_write();
-
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);
-
- // 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]);
- }
+ if (load_model)
+ source->load_model();
- if (redisplay_events)
- region_view->add_event(ev);
+ if (source->model()) {
+ // Find our note range
+ for (size_t i=0; i < source->model()->n_notes(); ++i) {
+ const MidiModel::Note& note = source->model()->note_at(i);
+ update_bounds(note.note());
+ }
}
- if (redisplay_events)
- region_view->end_write();
+ // Display region contents
+ region_view->display_model(source->model());
+}
+
+void
+MidiStreamView::display_diskstream (boost::shared_ptr<Diskstream> ds)
+{
+ StreamView::display_diskstream(ds);
+ draw_note_separators();
}
// FIXME: code duplication with AudioStreamView
list<RegionView *>::iterator i, tmp;
for (i = region_views.begin(); i != region_views.end(); ++i) {
+ (*i)->enable_display(true); // FIXME: double display
(*i)->set_valid (false);
+
+ /* FIXME: slow. MidiRegionView needs a find_note_range method
+ * that finds the range without wasting time drawing the events */
+
+ // Load model if it isn't already, to get note range
+ MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*i);
+ mrv->midi_region()->midi_source(0)->load_model();
}
- _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);
delete *i;
region_views.erase (i);
} else {
+ (*i)->enable_display(true);
(*i)->set_y_position_and_height(0, height); // apply note range
}
i = tmp;
}
-
+
/* now fix layering */
for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
region_layered (*i);
}
+
+ draw_note_separators();
+}
+
+
+void
+MidiStreamView::update_contents_y_position_and_height ()
+{
+ StreamView::update_contents_y_position_and_height();
+ draw_note_separators();
+}
+
+void
+MidiStreamView::draw_note_separators()
+{
+ for (uint8_t i=0; i < 127; ++i) {
+ if (i >= _lowest_note-1 && i <= _highest_note) {
+ _note_lines[i]->property_x1() = 0;
+ _note_lines[i]->property_x2() = canvas_rect->property_x2() - 2;
+ _note_lines[i]->property_y1() = note_to_y(i);
+ _note_lines[i]->property_y2() = note_to_y(i);
+ _note_lines[i]->show();
+ _note_lines[i]->raise_to_top();
+ } else {
+ _note_lines[i]->hide();
+ }
+ }
+}
+
+
+void
+MidiStreamView::update_bounds(uint8_t note_num)
+{
+ _lowest_note = min(_lowest_note, note_num);
+ _highest_note = max(_highest_note, note_num);
}
/* draw events */
MidiRegionView* mrv = (MidiRegionView*)iter->second;
- for (size_t i = 0; i < data->size(); ++i) {
- const MidiEvent& ev = (*data.get())[i];
+ for (MidiBuffer::iterator i = data->begin(); i != data->end(); ++i) {
+ const MidiEvent& ev = *i;
mrv->add_event(ev);
mrv->extend_active_notes();
}