MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr<MidiRegion> r, double spu,
Gdk::Color& basic_color)
: RegionView (parent, tv, r, spu, basic_color)
+ , _default_note_length(0.0)
, _active_notes(0)
, _delta_command(NULL)
, _command_mode(None)
MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr<MidiRegion> r, double spu,
Gdk::Color& basic_color, TimeAxisViewItem::Visibility visibility)
: RegionView (parent, tv, r, spu, basic_color, visibility)
+ , _default_note_length(0.0)
, _active_notes(0)
, _delta_command(NULL)
, _command_mode(None)
{
if (wfd)
midi_region()->midi_source(0)->load_model();
+
+ const Meter& m = trackview.session().tempo_map().meter_at(_region->start());
+ const Tempo& t = trackview.session().tempo_map().tempo_at(_region->start());
+ _default_note_length = m.frames_per_bar(t, trackview.session().frame_rate())
+ / m.beats_per_bar();
_model = midi_region()->midi_source(0)->model();
_enable_display = false;
bool
MidiRegionView::canvas_event(GdkEvent* ev)
{
- enum State { None, Pressed, Dragging };
+ enum State { None, Pressed, SelectDragging, AddDragging };
static int press_button = 0;
static State _state;
+ static double drag_start_x, drag_start_y;
static double last_x, last_y;
double event_x, event_y;
- static ArdourCanvas::SimpleRect* select_rect = NULL;
+ static ArdourCanvas::SimpleRect* drag_rect = NULL;
if (trackview.editor.current_mouse_mode() != MouseNote)
return false;
switch (_state) {
case Pressed: // Drag start
- cerr << "PRESSED MOTION: " << press_button << endl;
- if (press_button == 1) { // Select rect start
+
+ if (press_button == 1 && _command_mode != Remove) { // Select rect start
group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
- _state = Dragging;
last_x = event_x;
last_y = event_y;
+ drag_start_x = event_x;
+ drag_start_y = event_y;
+
+ drag_rect = new ArdourCanvas::SimpleRect(*group);
+ drag_rect->property_x1() = event_x;
+ drag_rect->property_y1() = event_y;
+ drag_rect->property_x2() = event_x;
+ drag_rect->property_y2() = event_y;
+ drag_rect->property_outline_what() = 0xFF;
+ drag_rect->property_outline_color_rgba() = 0xFF000099;
+ drag_rect->property_fill_color_rgba() = 0xFFDDDD33;
+
+ _state = SelectDragging;
+ return true;
- select_rect = new ArdourCanvas::SimpleRect(*group);
- select_rect->property_x1() = event_x;
- select_rect->property_y1() = event_y;
- select_rect->property_x2() = event_x;
- select_rect->property_y2() = event_y;
- select_rect->property_outline_color_rgba() = 0xFF000099;
- select_rect->property_fill_color_rgba() = 0xFFDDDD33;
-
+ } else if (press_button == 3) { // Add note drag start
+ group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
+ Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
+ last_x = event_x;
+ last_y = event_y;
+ drag_start_x = event_x;
+ drag_start_y = event_y;
+
+ nframes_t event_frame = midi_view()->editor.pixel_to_frame(event_x);
+ midi_view()->editor.snap_to(event_frame);
+
+ drag_rect = new ArdourCanvas::SimpleRect(*group);
+ drag_rect->property_x1() = midi_view()->editor.frame_to_pixel(event_frame);
+
+ drag_rect->property_y1() = midi_stream_view()->note_to_y(midi_stream_view()->y_to_note(event_y));
+ drag_rect->property_x2() = event_x;
+ drag_rect->property_y2() = drag_rect->property_y1() + floor(midi_stream_view()->note_height());
+ drag_rect->property_outline_what() = 0xFF;
+ drag_rect->property_outline_color_rgba() = 0xFFFFFF99;
+ drag_rect->property_fill_color_rgba() = 0xFFFFFF66;
+
+ _state = AddDragging;
return true;
}
- _state = Dragging;
+
break;
- case Dragging: // Select rect motion
+ case SelectDragging: // Select rect motion
+ case AddDragging: // Add note rect motion
if (ev->motion.is_hint) {
int t_x;
int t_y;
event_y = t_y;
}
- if (select_rect) {
- select_rect->property_x2() = event_x;
- select_rect->property_y2() = event_y;
+ if (_state == AddDragging) {
+ nframes_t event_frame = midi_view()->editor.pixel_to_frame(event_x);
+ midi_view()->editor.snap_to(event_frame);
+ event_x = midi_view()->editor.frame_to_pixel(event_frame);
}
+ if (drag_rect)
+ drag_rect->property_x2() = event_x;
+
+ if (drag_rect && _state == SelectDragging)
+ drag_rect->property_y2() = event_y;
+
last_x = event_x;
last_y = event_y;
break;
case GDK_BUTTON_RELEASE:
+ event_x = ev->motion.x;
+ event_y = ev->motion.y;
+ group->w2i(event_x, event_y);
group->ungrab(ev->button.time);
switch (_state) {
case Pressed: // Clicked
- if (ev->button.button == 1)
- create_note_at(ev->button.x, ev->button.y);
+ if (ev->button.button == 3) {
+ nframes_t event_frame = midi_view()->editor.pixel_to_frame(event_x);
+ midi_view()->editor.snap_to(event_frame);
+ event_x = midi_view()->editor.frame_to_pixel(event_frame);
+ create_note_at(event_x, event_y, _default_note_length);
+ }
_state = None;
return true;
- case Dragging: // Select rect done
+ case SelectDragging: // Select drag done
_state = None;
- delete select_rect;
- select_rect = NULL;
+ delete drag_rect;
+ drag_rect = NULL;
+ return true;
+ case AddDragging: // Add drag done
+ _state = None;
+ if (drag_rect->property_x2() > drag_rect->property_x1() + 2) {
+ create_note_at(drag_rect->property_x1(), drag_rect->property_y1(),
+ trackview.editor.pixel_to_frame(
+ drag_rect->property_x2() - drag_rect->property_x1()));
+ }
+
+ delete drag_rect;
+ drag_rect = NULL;
return true;
default:
break;
/** Add a note to the model, and the view, at a canvas (click) coordinate */
void
-MidiRegionView::create_note_at(double x, double y)
+MidiRegionView::create_note_at(double x, double y, double dur)
{
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;
-
- get_canvas_group()->w2i(x, y);
+ double note = midi_stream_view()->y_to_note(y);
- double note = floor((roll_height - y) / roll_height * (double)note_range) + view->lowest_note();
assert(note >= 0.0);
assert(note <= 127.0);
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();
+ //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);
if (midi_view()->note_mode() == Sustained) {
if ((ev.buffer()[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
const Byte& note = ev.buffer()[1];
- const double y1 = note_y(note);
+ 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 (
ev_rect->property_y1() = y1;
ev_rect->property_x2() = trackview.editor.frame_to_pixel (
_region->length());
- ev_rect->property_y2() = y1 + note_height();
+ ev_rect->property_y2() = y1 + floor(midi_stream_view()->note_height());
ev_rect->property_outline_color_rgba() = 0xFFFFFFAA;
/* outline all but right edge */
ev_rect->property_outline_what() = (guint32) (0x1 & 0x4 & 0x8);
} else if (midi_view()->note_mode() == Percussive) {
const Byte& note = ev.buffer()[1];
- const double diamond_size = std::min(note_height(), 5.0);
+ 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 = note_y(note) + (diamond_size / 2.0);
+ const double y = midi_stream_view()->note_to_y(note) + (diamond_size / 2.0);
CanvasHit* ev_diamond = new CanvasHit(*this, *group, diamond_size);
ev_diamond->move(x, y);
assert(note.time() < _region->length());
//assert(note.time() + note.duration < _region->length());
- 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;
const uint8_t fill_alpha = 0x20 + (uint8_t)(note.velocity() * 1.5);
const uint32_t fill = RGBA_TO_UINT(0xE0 + note.velocity()/127.0 * 0x10, 0xE0, 0xE0, fill_alpha);
const uint8_t outline_alpha = 0x80 + (uint8_t)(note.velocity());
const uint32_t outline = RGBA_TO_UINT(0xE0 + note.velocity()/127.0 * 0x10, 0xE0, 0xE0, outline_alpha);
- //printf("Range: %d\n", note_range);
//printf("Event, time = %f, note = %d\n", note.time(), note.note());
-
- if (mtv->note_mode() == Sustained) {
- const double y1 = trackview.height - (pixel_range * (note.note() - view->lowest_note() + 1))
- - footer_height - 3.0;
+ if (midi_view()->note_mode() == Sustained) {
+ const double y1 = midi_stream_view()->note_to_y(note.note());
ArdourCanvas::SimpleRect * ev_rect = new CanvasNote(*this, *group, ¬e);
ev_rect->property_x1() = trackview.editor.frame_to_pixel((nframes_t)note.time());
ev_rect->property_y1() = y1;
ev_rect->property_x2() = trackview.editor.frame_to_pixel((nframes_t)(note.end_time()));
- ev_rect->property_y2() = y1 + ceil(pixel_range);
+ ev_rect->property_y2() = y1 + floor(midi_stream_view()->note_height());
ev_rect->property_fill_color_rgba() = fill;
ev_rect->property_outline_color_rgba() = outline;
ev_rect->show();
_events.push_back(ev_rect);
- } else if (mtv->note_mode() == Percussive) {
+ } else if (midi_view()->note_mode() == Percussive) {
+ const double diamond_size = midi_stream_view()->note_height() / 2.0;
const double x = trackview.editor.frame_to_pixel((nframes_t)note.time());
- const double y = trackview.height - (pixel_range * (note.note() - view->lowest_note() + 1))
- - footer_height - 3.0;
+ const double y = midi_stream_view()->note_to_y(note.note()) + (diamond_size / 2.0) - 2;
- CanvasHit* ev_diamond = new CanvasHit(*this, *group, std::min(pixel_range, 5.0), ¬e);
+ CanvasHit* ev_diamond = new CanvasHit(*this, *group, diamond_size);
ev_diamond->move(x, y);
ev_diamond->show();
ev_diamond->property_fill_color_rgba() = fill;