mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 16:46:35 +01:00
Merge the two separate 'add notes to midi region' interfaces (note and midievent).
Update note range dynamically while recording to fit incoming notes. git-svn-id: svn://localhost/ardour2/trunk@2512 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
9bcd3f1d16
commit
79db28b0b8
8 changed files with 79 additions and 82 deletions
|
|
@ -31,15 +31,24 @@ namespace Gnome {
|
||||||
namespace Canvas {
|
namespace Canvas {
|
||||||
|
|
||||||
|
|
||||||
CanvasMidiEvent::CanvasMidiEvent(MidiRegionView& region, Item* item, const ARDOUR::Note* note)
|
CanvasMidiEvent::CanvasMidiEvent(MidiRegionView& region, Item* item, const ARDOUR::Note* note, bool copy_note)
|
||||||
: _region(region)
|
: _region(region)
|
||||||
, _item(item)
|
, _item(item)
|
||||||
, _state(None)
|
, _state(None)
|
||||||
, _note(note)
|
, _note((copy_note && note) ? new ARDOUR::Note(*note) : note)
|
||||||
|
, _own_note(copy_note)
|
||||||
, _selected(false)
|
, _selected(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CanvasMidiEvent::~CanvasMidiEvent()
|
||||||
|
{
|
||||||
|
if (_own_note)
|
||||||
|
delete _note;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CanvasMidiEvent::selected(bool yn)
|
CanvasMidiEvent::selected(bool yn)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ namespace Canvas {
|
||||||
*/
|
*/
|
||||||
class CanvasMidiEvent {
|
class CanvasMidiEvent {
|
||||||
public:
|
public:
|
||||||
CanvasMidiEvent(MidiRegionView& region, Item* item, const ARDOUR::Note* note = NULL);
|
CanvasMidiEvent(MidiRegionView& region, Item* item, const ARDOUR::Note* note=NULL, bool copy_note=false);
|
||||||
virtual ~CanvasMidiEvent() {}
|
virtual ~CanvasMidiEvent();
|
||||||
|
|
||||||
bool on_event(GdkEvent* ev);
|
bool on_event(GdkEvent* ev);
|
||||||
|
|
||||||
|
|
@ -71,6 +71,7 @@ protected:
|
||||||
Item* const _item;
|
Item* const _item;
|
||||||
State _state;
|
State _state;
|
||||||
const ARDOUR::Note* _note;
|
const ARDOUR::Note* _note;
|
||||||
|
bool _own_note;
|
||||||
bool _selected;
|
bool _selected;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ namespace Canvas {
|
||||||
|
|
||||||
class CanvasNote : public SimpleRect, public CanvasMidiEvent {
|
class CanvasNote : public SimpleRect, public CanvasMidiEvent {
|
||||||
public:
|
public:
|
||||||
CanvasNote(MidiRegionView& region, Group& group, const ARDOUR::Note* note=NULL)
|
CanvasNote(MidiRegionView& region, Group& group, const ARDOUR::Note* note=NULL, bool copy_note=false)
|
||||||
: SimpleRect(group), CanvasMidiEvent(region, this, note)
|
: SimpleRect(group), CanvasMidiEvent(region, this, note, copy_note)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -406,7 +406,7 @@ MidiRegionView::redisplay_model()
|
||||||
_model->read_lock();
|
_model->read_lock();
|
||||||
|
|
||||||
for (size_t i=0; i < _model->n_notes(); ++i)
|
for (size_t i=0; i < _model->n_notes(); ++i)
|
||||||
add_note(_model->note_at(i));
|
add_note(_model->note_at(i), false);
|
||||||
|
|
||||||
end_write();
|
end_write();
|
||||||
|
|
||||||
|
|
@ -495,8 +495,23 @@ MidiRegionView::set_y_position_and_height (double y, double h)
|
||||||
{
|
{
|
||||||
RegionView::set_y_position_and_height(y, h - 1);
|
RegionView::set_y_position_and_height(y, h - 1);
|
||||||
|
|
||||||
if (_enable_display)
|
if (_enable_display) {
|
||||||
redisplay_model();
|
|
||||||
|
_model->read_lock();
|
||||||
|
|
||||||
|
for (std::vector<CanvasMidiEvent*>::const_iterator i = _events.begin(); i != _events.end(); ++i) {
|
||||||
|
CanvasNote* note = dynamic_cast<CanvasNote*>(*i);
|
||||||
|
if (note && note->note()) {
|
||||||
|
const double y1 = midi_stream_view()->note_to_y(note->note()->note());
|
||||||
|
const double y2 = y1 + floor(midi_stream_view()->note_height());
|
||||||
|
|
||||||
|
note->property_y1() = y1;
|
||||||
|
note->property_y2() = y2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_model->read_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
if (name_text) {
|
if (name_text) {
|
||||||
name_text->raise_to_top();
|
name_text->raise_to_top();
|
||||||
|
|
@ -544,69 +559,19 @@ MidiRegionView::end_write()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Add a MIDI event.
|
/** Resolve an active MIDI note (while recording).
|
||||||
*
|
|
||||||
* This is used while recording, and handles displaying still-unresolved notes.
|
|
||||||
* Displaying an existing model is simpler, and done with add_note.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
MidiRegionView::add_event (const MidiEvent& ev)
|
MidiRegionView::resolve_note(uint8_t note, double end_time)
|
||||||
{
|
{
|
||||||
/*printf("MRV add Event, time = %f, size = %u, data = ", ev.time(), ev.size());
|
if (midi_view()->note_mode() != Sustained)
|
||||||
for (size_t i=0; i < ev.size(); ++i) {
|
return;
|
||||||
printf("%X ", ev.buffer()[i]);
|
|
||||||
}
|
|
||||||
printf("\n\n");*/
|
|
||||||
|
|
||||||
//ArdourCanvas::Group* const group = (ArdourCanvas::Group*)get_canvas_group();
|
|
||||||
ArdourCanvas::Group* const group = _note_group;
|
|
||||||
|
|
||||||
if (midi_view()->note_mode() == Sustained) {
|
|
||||||
if ((ev.buffer()[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
|
|
||||||
const Byte& note = ev.buffer()[1];
|
|
||||||
const double y1 = midi_stream_view()->note_to_y(note);
|
|
||||||
|
|
||||||
CanvasNote* ev_rect = new CanvasNote(*this, *group);
|
|
||||||
ev_rect->property_x1() = trackview.editor.frame_to_pixel (
|
|
||||||
(nframes_t)ev.time());
|
|
||||||
ev_rect->property_y1() = y1;
|
|
||||||
ev_rect->property_x2() = trackview.editor.frame_to_pixel (
|
|
||||||
_region->length());
|
|
||||||
ev_rect->property_y2() = y1 + floor(midi_stream_view()->note_height());
|
|
||||||
ev_rect->property_fill_color_rgba() = note_fill_color(ev.velocity());
|
|
||||||
ev_rect->property_outline_color_rgba() = note_outline_color(ev.velocity());
|
|
||||||
/* outline all but right edge */
|
|
||||||
ev_rect->property_outline_what() = (guint32) (0x1 & 0x4 & 0x8);
|
|
||||||
|
|
||||||
ev_rect->raise_to_top();
|
|
||||||
|
|
||||||
_events.push_back(ev_rect);
|
|
||||||
if (_active_notes)
|
|
||||||
_active_notes[note] = ev_rect;
|
|
||||||
|
|
||||||
} else if ((ev.buffer()[0] & 0xF0) == MIDI_CMD_NOTE_OFF) {
|
|
||||||
const Byte& note = ev.buffer()[1];
|
|
||||||
if (_active_notes && _active_notes[note]) {
|
if (_active_notes && _active_notes[note]) {
|
||||||
_active_notes[note]->property_x2() = trackview.editor.frame_to_pixel((nframes_t)ev.time());
|
_active_notes[note]->property_x2() = trackview.editor.frame_to_pixel((nframes_t)end_time);
|
||||||
_active_notes[note]->property_outline_what() = (guint32) 0xF; // all edges
|
_active_notes[note]->property_outline_what() = (guint32) 0xF; // all edges
|
||||||
_active_notes[note] = NULL;
|
_active_notes[note] = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} else if (midi_view()->note_mode() == Percussive) {
|
|
||||||
const Byte& note = ev.buffer()[1];
|
|
||||||
const double diamond_size = midi_stream_view()->note_height() / 2.0;
|
|
||||||
const double x = trackview.editor.frame_to_pixel((nframes_t)ev.time());
|
|
||||||
const double y = midi_stream_view()->note_to_y(note) + ((diamond_size-2) / 4.0);
|
|
||||||
|
|
||||||
CanvasHit* ev_diamond = new CanvasHit(*this, *group, diamond_size);
|
|
||||||
ev_diamond->move(x, y);
|
|
||||||
ev_diamond->show();
|
|
||||||
ev_diamond->property_fill_color_rgba() = note_fill_color(ev.velocity());
|
|
||||||
ev_diamond->property_outline_color_rgba() = note_outline_color(ev.velocity());
|
|
||||||
|
|
||||||
_events.push_back(ev_diamond);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -626,11 +591,12 @@ MidiRegionView::extend_active_notes()
|
||||||
|
|
||||||
/** Add a MIDI note to the view (with duration).
|
/** Add a MIDI note to the view (with duration).
|
||||||
*
|
*
|
||||||
* This does no 'realtime' note resolution, notes from a MidiModel have a
|
* If in sustained mode, notes with duration 0 will be considered active
|
||||||
* duration so they can be drawn in full immediately.
|
* notes, and resolve_note should be called when the corresponding note off
|
||||||
|
* event arrives, to properly display the note.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
MidiRegionView::add_note (const Note& note)
|
MidiRegionView::add_note (const Note& note, bool copy_note)
|
||||||
{
|
{
|
||||||
assert(note.time() >= 0);
|
assert(note.time() >= 0);
|
||||||
//assert(note.time() < _region->length());
|
//assert(note.time() < _region->length());
|
||||||
|
|
@ -640,15 +606,26 @@ MidiRegionView::add_note (const Note& note)
|
||||||
if (midi_view()->note_mode() == Sustained) {
|
if (midi_view()->note_mode() == Sustained) {
|
||||||
const double y1 = midi_stream_view()->note_to_y(note.note());
|
const double y1 = midi_stream_view()->note_to_y(note.note());
|
||||||
|
|
||||||
CanvasNote* ev_rect = new CanvasNote(*this, *group, ¬e);
|
CanvasNote* ev_rect = new CanvasNote(*this, *group, ¬e, copy_note);
|
||||||
ev_rect->property_x1() = trackview.editor.frame_to_pixel((nframes_t)note.time());
|
ev_rect->property_x1() = trackview.editor.frame_to_pixel((nframes_t)note.time());
|
||||||
ev_rect->property_y1() = y1;
|
ev_rect->property_y1() = y1;
|
||||||
|
if (note.duration() > 0)
|
||||||
ev_rect->property_x2() = trackview.editor.frame_to_pixel((nframes_t)(note.end_time()));
|
ev_rect->property_x2() = trackview.editor.frame_to_pixel((nframes_t)(note.end_time()));
|
||||||
|
else
|
||||||
|
ev_rect->property_x2() = trackview.editor.frame_to_pixel(_region->length());
|
||||||
ev_rect->property_y2() = y1 + floor(midi_stream_view()->note_height());
|
ev_rect->property_y2() = y1 + floor(midi_stream_view()->note_height());
|
||||||
|
|
||||||
ev_rect->property_fill_color_rgba() = note_fill_color(note.velocity());
|
ev_rect->property_fill_color_rgba() = note_fill_color(note.velocity());
|
||||||
ev_rect->property_outline_color_rgba() = note_outline_color(note.velocity());
|
ev_rect->property_outline_color_rgba() = note_outline_color(note.velocity());
|
||||||
ev_rect->property_outline_what() = (guint32) 0xF; // all edges
|
|
||||||
|
if (note.duration() == 0) {
|
||||||
|
_active_notes[note.note()] = ev_rect;
|
||||||
|
/* outline all but right edge */
|
||||||
|
ev_rect->property_outline_what() = (guint32) (0x1 & 0x4 & 0x8);
|
||||||
|
} else {
|
||||||
|
/* outline all edges */
|
||||||
|
ev_rect->property_outline_what() = (guint32) 0xF;
|
||||||
|
}
|
||||||
|
|
||||||
ev_rect->show();
|
ev_rect->show();
|
||||||
_events.push_back(ev_rect);
|
_events.push_back(ev_rect);
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,8 @@ class MidiRegionView : public RegionView
|
||||||
|
|
||||||
GhostRegion* add_ghost (AutomationTimeAxisView&);
|
GhostRegion* add_ghost (AutomationTimeAxisView&);
|
||||||
|
|
||||||
void add_event(const ARDOUR::MidiEvent& ev);
|
void add_note(const ARDOUR::Note& note, bool copy_note);
|
||||||
void add_note(const ARDOUR::Note& note);
|
void resolve_note(uint8_t note_num, double end_time);
|
||||||
|
|
||||||
void begin_write();
|
void begin_write();
|
||||||
void end_write();
|
void end_write();
|
||||||
|
|
|
||||||
|
|
@ -417,6 +417,7 @@ MidiStreamView::update_rec_regions (boost::shared_ptr<MidiModel> data, nframes_t
|
||||||
if (use_rec_regions) {
|
if (use_rec_regions) {
|
||||||
|
|
||||||
uint32_t n = 0;
|
uint32_t n = 0;
|
||||||
|
bool update_range = false;
|
||||||
|
|
||||||
for (list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) {
|
for (list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) {
|
||||||
|
|
||||||
|
|
@ -474,14 +475,18 @@ MidiStreamView::update_rec_regions (boost::shared_ptr<MidiModel> data, nframes_t
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (note.time() >= start)
|
if (note.time() >= start)
|
||||||
if (data->note_mode() == Percussive || note.duration() > 0)
|
mrv->add_note(note, true);
|
||||||
mrv->add_note(note);
|
|
||||||
else
|
|
||||||
mrv->add_event(note.on_event());
|
|
||||||
|
|
||||||
if (note.duration() > 0 && note.end_time() >= start)
|
if (note.duration() > 0 && note.end_time() >= start)
|
||||||
mrv->add_event(note.off_event());
|
mrv->resolve_note(note.note(), note.end_time());
|
||||||
|
|
||||||
|
if (note.note() < _lowest_note) {
|
||||||
|
_lowest_note = note.note();
|
||||||
|
update_range = true;
|
||||||
|
} else if (note.note() > _highest_note) {
|
||||||
|
_highest_note = note.note();
|
||||||
|
update_range = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mrv->extend_active_notes();
|
mrv->extend_active_notes();
|
||||||
|
|
@ -517,6 +522,9 @@ MidiStreamView::update_rec_regions (boost::shared_ptr<MidiModel> data, nframes_t
|
||||||
|
|
||||||
iter = tmp;
|
iter = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (update_range)
|
||||||
|
update_contents_y_position_and_height();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,8 @@ Note::Note(const Note& copy)
|
||||||
: _on_event(copy._on_event, true)
|
: _on_event(copy._on_event, true)
|
||||||
, _off_event(copy._off_event, true)
|
, _off_event(copy._off_event, true)
|
||||||
{
|
{
|
||||||
|
assert(_on_event.buffer());
|
||||||
|
assert(_off_event.buffer());
|
||||||
/*
|
/*
|
||||||
assert(copy._on_event.size == 3);
|
assert(copy._on_event.size == 3);
|
||||||
_on_event.buffer = _on_event_buffer;
|
_on_event.buffer = _on_event_buffer;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue