View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0010169 | ardour | bugs | public | 2026-02-10 03:05 | 2026-03-13 22:35 |
| Reporter | pyrotek45 | Assigned To | |||
| Priority | normal | Severity | major | Reproducibility | always |
| Status | new | Resolution | open | ||
| Platform | GNU | OS | Linux | OS Version | (any) |
| Product Version | 9.0 | ||||
| Summary | 0010169: Piano roll doesnt have the same shortcuts as regular midi editing. | ||||
| Description | many mouse shortcuts that you would do in the midi editing in the playlist do not seem to work in the piano roll. things like middle click to delete. Doing a simple select and ctrl + drag works but its starts with a weird offset. there doesn't seem to be a stop button for the piano roll. pressing play over and over doesn't seem to stop the playback. the piano roll is an amazing feature, and im so glad its here. finally. but im just wanting it to be perfect. it should behave with all the same shortcuts that im used to on the playlist. currently that is not the case. | ||||
| Steps To Reproduce | try using middle mouse click to delete notes in the piano roll. try selecting and dragging notes in the piano roll to see the weird visual offset. mine gets offset to the left visually, everytime. and just as a tweak i think the piano roll should also have a stop button. or make it so the play button works as a stop button if its currently playing. | ||||
| Tags | No tags attached. | ||||
|
|
> i think the piano roll should also have a stop button. or make it so the play button works as a stop button if its currently playing. for timeline regions or for clips? the play button does entirely different things in each case ... in general (and also, notable in Live and Bitwig) you can't stop a playing clip from its own controls, which I admit I find a bit odd (but we copied it anyway). |
|
|
honestly the play button is just odd, but i could live with it. the important thing to me is the keyboard and mouse controls dont seem to work in the lower piano roll, or in a separate window. also, i was mainly talking about time line regions. if i make a midi section, double click to open the piano roll. and press play, it seems i *have* to press the spacebar for it to stop. this is kinda awkward in full-screen mode. but not a real issue if you mainly use the spacebar. but otherwise , once you press the play button , it just goes forever. another thing to note is, in the bottom section ( the piano roll section ), i cant seem to grab ( or find a place to grab ) the section in which to resize it. is that by design or is there a spot im just not finding? |
|
|
the lack of resize is intentional. we went over this many times with many users during the development of 9.0 and for now have settled on this zone not being resizable. that is not cast in stone, but it's the way it is for now. You can change the editing style to use a separate window, and that is resizable. |
|
|
ok, middle button function restored to pianoroll now too, as of ac26912bacaebf |
|
|
also, there is a weird bug where, in the piano roll, the bottom section or the stand alone window. if you use multi select on some midi note and hold control, then drag, you will see the midi notes that you are dragging are not in the correct spot. i wish there was a way where i could just video call or smth because i feel like i find so many little paper cuts like this all the time. anyways, it would be nice if that bug was patched, currently i cant control and drag midi notes because they just dont work, they appear all the way to the right for some reason, and then when i let go of the button to paste, it paste not where the preview notes were shown. |
|
|
how are you making the "preview notes" appear? |
|
|
select some notes, hold control, then drag. |
|
|
any update? i can provide more videos if needed. but really hoping the piano roll becomes stable soon. |
|
|
there's a year or more's worth of work on the pianoroll, currently underway. no update on this specific bug. |
|
|
@paul "there's a year or more's worth of work on the pianoroll" ... 0___0 : ( |
|
|
i used ai to ask if it could fix this bug and it did it in 3 minutes. ill look into how to do a pull request on github because its only a few lines of code. but it fixed the midi move copies to work correctly for me. here is what it did. this was done in the midi_view.cc file. -- 1. Drag-copy notes don't visually align (midi_view.cc) MidiView::move_copies() doesn't match the coordinate transform logic in MidiView::move_selection(). Three issues: Uses source_beats_to_absolute_time() unconditionally instead of checking _on_timeline (which is false in the standalone piano roll) Missing canvas_to_timeline() call when subtracting the note's canvas position — time_to_pixel_unrounded() returns timeline-relative coords but item_to_canvas() returns canvas coords, so they're off by _timeline_origin (the keyboard header width) Missing timeline_to_canvas() conversion for the note length endpoint The fix is to make move_copies() use the same pattern as move_selection(): Same pattern applied to Hit handling and the sustained note length (timeline_to_canvas added before -- now the notes work just fine. it even fixed some other issues like the boundaries not being checked properly in the piano roll. I wasnt able to click notes into the eddges of the piano roll. -- 2. Can't select notes near left edge — StartBoundaryRect::covers() (boundary.cc) Operator precedence bug — the comparison is inside fabs(): 3. Can't select notes near right edge — EndBoundaryRect::covers() (boundary.cc) The condition (point.x >= self.x0) matches everything to the right of the boundary rect's left edge, which is essentially the entire note canvas: Bugs 2 and 3 cause the clip start/end boundary handles to swallow mouse events across most of the canvas, preventing note selection near the edges. -- hopefully these notes help. |
|
|
heres the snippets i forgot to add earlier. for the midi copies fix // === MidiView::move_copies() === // BEFORE (broken): for (CopyDragEvents::iterator i = _copy_drag_events.begin(); i != _copy_drag_events.end(); ++i) { NoteBase* n = *i; if (n->note()->time() == earliest) { to_play.push_back (n->note()); } timepos_t const note_time_qn = _midi_region->source_beats_to_absolute_time (n->note()->time()); double_t dx = 0; if (_midi_context.note_mode() == Sustained) { dx = _editing_context.time_to_pixel_unrounded (timepos_t (note_time_qn) + dx_qn) - n->item()->item_to_canvas (ArdourCanvas::Duple (n->x0(), 0)).x; } else { Hit* hit = dynamic_cast<Hit*>(n); if (hit) { dx = _editing_context.time_to_pixel_unrounded (timepos_t (note_time_qn) + dx_qn) - n->item()->item_to_canvas (ArdourCanvas::Duple (((hit->x0() + hit->x1()) / 2.0) - hit->position().x, 0)).x; } } (*i)->move_event(dx, dy); if (_midi_context.note_mode() == Sustained) { Note* sus = dynamic_cast<Note*> (*i); double const len_dx = _editing_context.time_to_pixel_unrounded (timepos_t (note_time_qn) + dx_qn + timecnt_t (n->note()->length())); sus->set_x1 (n->item()->canvas_to_item (ArdourCanvas::Duple (len_dx, 0)).x); } } // AFTER (fixed — matches move_selection() logic): for (CopyDragEvents::iterator i = _copy_drag_events.begin(); i != _copy_drag_events.end(); ++i) { NoteBase* n = *i; if (n->note()->time() == earliest) { to_play.push_back (n->note()); } Temporal::Beats note_time_qn; double_t dx = 0; if (!_on_timeline) { note_time_qn = n->note()->time (); } else { note_time_qn = _midi_region->source_beats_to_absolute_beats (n->note()->time()); } if (_midi_context.note_mode() == Sustained) { dx = _editing_context.time_to_pixel_unrounded (timepos_t (note_time_qn + dx_qn.beats())); dx -= _editing_context.canvas_to_timeline (n->item()->item_to_canvas (ArdourCanvas::Duple (n->x0(), 0)).x); } else { Hit* hit = dynamic_cast<Hit*>(n); if (hit) { dx = _editing_context.time_to_pixel_unrounded (timepos_t (note_time_qn + dx_qn.beats())); dx -= _editing_context.canvas_to_timeline (n->item()->item_to_canvas (ArdourCanvas::Duple (((hit->x0() + hit->x1()) / 2.0) - hit->position().x, 0)).x); } } (*i)->move_event(dx, dy); if (_midi_context.note_mode() == Sustained) { Note* sus = dynamic_cast<Note*> (*i); double len_dx = _editing_context.time_to_pixel_unrounded (timepos_t (note_time_qn) + dx_qn + timecnt_t (n->note()->length())); len_dx = _editing_context.timeline_to_canvas (len_dx); sus->set_x1 (n->item()->canvas_to_item (ArdourCanvas::Duple (len_dx, 0)).x); } } and how to fix the boundaries bug. // === StartBoundaryRect::covers() === // BEFORE (broken — comparison inside fabs): bool StartBoundaryRect::covers (ArdourCanvas::Duple const & point) const { ArdourCanvas::Rect self (item_to_window (_rect)); const double scale = UIConfiguration::instance().get_ui_scale(); if ((point.x < self.x0) || (fabs ((point.x - self.x1) < (20. * scale)))) { /* before the start, or within 20 (scaled) pixels of the boundary, on the right */ return true; } // AFTER (fixed): bool StartBoundaryRect::covers (ArdourCanvas::Duple const & point) const { ArdourCanvas::Rect self (item_to_window (_rect)); const double scale = UIConfiguration::instance().get_ui_scale(); if ((point.x < self.x0) || (fabs (point.x - self.x1) < (20. * scale))) { /* before the start, or within 20 (scaled) pixels of the boundary, on either side */ return true; } // === EndBoundaryRect::covers() === // BEFORE (broken — first condition covers entire canvas): bool EndBoundaryRect::covers (ArdourCanvas::Duple const & point) const { ArdourCanvas::Rect self (item_to_window (_rect)); const double scale = UIConfiguration::instance().get_ui_scale(); if ((point.x >= self.x0) || ((self.x0 - point.x) < (20. * scale))) { /* paste the edge, or within 20 (scaled) pixels of the edge */ return true; } // AFTER (fixed): bool EndBoundaryRect::covers (ArdourCanvas::Duple const & point) const { ArdourCanvas::Rect self (item_to_window (_rect)); const double scale = UIConfiguration::instance().get_ui_scale(); if ((point.x > self.x1) || (fabs (point.x - self.x0) < (20. * scale))) { /* past the end, or within 20 (scaled) pixels of the boundary, on either side */ return true; } |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2026-02-10 03:05 | pyrotek45 | New Issue | |
| 2026-02-12 00:15 | paul | Note Added: 0029862 | |
| 2026-02-12 00:33 | pyrotek45 | Note Added: 0029863 | |
| 2026-02-12 21:59 | paul | Note Added: 0029870 | |
| 2026-02-13 01:28 | paul | Note Added: 0029871 | |
| 2026-02-26 20:30 | pyrotek45 | Note Added: 0030004 | |
| 2026-02-26 20:30 | pyrotek45 | File Added: Screencast_20260226_152940.webm | |
| 2026-02-26 20:36 | paul | Note Added: 0030005 | |
| 2026-02-26 20:46 | pyrotek45 | Note Added: 0030006 | |
| 2026-03-06 23:22 | pyrotek45 | Note Added: 0030055 | |
| 2026-03-07 16:36 | paul | Note Added: 0030061 | |
| 2026-03-07 20:33 | GhostsonAcid | Note Added: 0030062 | |
| 2026-03-13 22:33 | pyrotek45 | Note Added: 0030104 | |
| 2026-03-13 22:35 | pyrotek45 | Note Added: 0030105 |