Skip to content

Commit a0bc141

Browse files
authored
Provide feedback when inserting notes using f1-f12 step input. (issue #1247, PR #1253)
1 parent c4dc06f commit a0bc141

File tree

3 files changed

+48
-10
lines changed

3 files changed

+48
-10
lines changed

src/midiEditorCommands.cpp

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,18 +1223,15 @@ void postMidiMovePitchCursor(int command) {
12231223
}
12241224
}
12251225

1226-
void cmdMidiInsertNote(Command* command) {
1226+
void cmdhInsertNote(int oldCount, int relativeNote, bool reportNewPos) {
12271227
HWND editor = MIDIEditor_GetActive();
12281228
MediaItem_Take* take = MIDIEditor_GetTake(editor);
1229-
int oldCount;
1230-
MIDI_CountEvts(take, &oldCount, nullptr, nullptr);
1231-
MIDIEditor_OnCommand(editor, command->gaccel.accel.cmd);
12321229
int newCount;
12331230
MIDI_CountEvts(take, &newCount, nullptr, nullptr);
12341231
if (newCount <= oldCount) {
12351232
return; // Not inserted.
12361233
}
1237-
int pitch = MIDIEditor_GetSetting_int(editor, "active_note_row");
1234+
int pitch = MIDIEditor_GetSetting_int(editor, "active_note_row") + relativeNote;
12381235
// Get selected notes.
12391236
vector<MidiNote> selectedNotes = getSelectedNotes(take);
12401237
// Find the just inserted note based on its pitch, as that makes it unique.
@@ -1250,9 +1247,6 @@ void cmdMidiInsertNote(Command* command) {
12501247
previewNotes(take, {note});
12511248
fakeFocus = FOCUS_NOTE;
12521249
ostringstream s;
1253-
// If we're advancing the cursor position, we should report the new position.
1254-
const bool reportNewPos = command->gaccel.accel.cmd ==
1255-
40051; // Edit: Insert note at edit cursor
12561250
if (settings::reportNotes) {
12571251
s << getMidiNoteName(take, note.pitch, note.channel) << " ";
12581252
s << formatNoteLength(note.start, note.end);
@@ -1266,6 +1260,18 @@ void cmdMidiInsertNote(Command* command) {
12661260
outputMessage(s);
12671261
}
12681262

1263+
void cmdMidiInsertNote(Command* command) {
1264+
HWND editor = MIDIEditor_GetActive();
1265+
MediaItem_Take* take = MIDIEditor_GetTake(editor);
1266+
int oldCount;
1267+
MIDI_CountEvts(take, &oldCount, nullptr, nullptr);
1268+
MIDIEditor_OnCommand(editor, command->gaccel.accel.cmd);
1269+
// If we're advancing the cursor position, we should report the new position.
1270+
const bool reportNewPos = command->gaccel.accel.cmd ==
1271+
40051; // Edit: Insert note at edit cursor
1272+
cmdhInsertNote(oldCount, 0, reportNewPos);
1273+
}
1274+
12691275
void cmdMidiPasteEvents(Command* command) {
12701276
HWND editor = MIDIEditor_GetActive();
12711277
MediaItem_Take* take = MIDIEditor_GetTake(editor);
@@ -2413,3 +2419,28 @@ void postMidiChangeZoom(int command) {
24132419
outputMessage(format(translate("{} pixels/second"), formatDouble(zoom, 1)));
24142420
}
24152421
}
2422+
2423+
// F1-f12 step input doesn't use actions, so we need to hook the key presses.
2424+
int midiStepTranslateAccel(MSG* msg, accelerator_register_t* accelReg) {
2425+
HWND editor = MIDIEditor_GetActive();
2426+
if (!editor || msg->message != WM_KEYDOWN || msg->wParam < VK_F1 ||
2427+
msg->wParam > VK_F12 ||
2428+
!GetToggleCommandState2(SectionFromUniqueID(MIDI_EDITOR_SECTION), 40053)) {
2429+
// This isn't for us.
2430+
return 0; // Normal handling.
2431+
}
2432+
MediaItem_Take* take = MIDIEditor_GetTake(editor);
2433+
int oldCount;
2434+
MIDI_CountEvts(take, &oldCount, nullptr, nullptr);
2435+
// F1 is the note at the pitch cursor, f2 is 1 semitone above, etc.
2436+
const int relativeNote = msg->wParam - VK_F1;
2437+
// If the shift key is being held, the cursor is not advancing, so we should
2438+
// not report the new position.
2439+
const bool reportNewPos = !(GetAsyncKeyState(VK_SHIFT) & 0x8000);
2440+
// We need to let the hook return so REAPER can handle the key and insert the
2441+
// note. We use CallLater to report the result.
2442+
CallLater([oldCount, relativeNote, reportNewPos] {
2443+
cmdhInsertNote(oldCount, relativeNote, reportNewPos);
2444+
}, 0);
2445+
return 0;
2446+
}

src/midiEditorCommands.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,4 @@ void postMidiToggleSnap(int command);
7474
void postMidiChangeZoom(int command);
7575
int countSelectedEvents(MediaItem_Take* take);
7676
const std::string getMidiNoteName(MediaTrack* track, int pitch, int channel);
77+
int midiStepTranslateAccel(MSG* msg, accelerator_register_t* accelReg);

src/reaper_osara.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6079,7 +6079,11 @@ HWINEVENTHOOK winEventHook = nullptr;
60796079
// This accelerator hook is registered at startup and remains registered until
60806080
// REAPER exits.
60816081
int translateAccel(MSG* msg, accelerator_register_t* accelReg) {
6082-
return vkbTranslateAccel(msg, accelReg);
6082+
int res = vkbTranslateAccel(msg, accelReg);
6083+
if (res != 0) {
6084+
return res;
6085+
}
6086+
return midiStepTranslateAccel(msg, accelReg);
60836087
}
60846088

60856089
extern "C" {
@@ -6156,7 +6160,9 @@ REAPER_PLUGIN_DLL_EXPORT int REAPER_PLUGIN_ENTRYPOINT(REAPER_PLUGIN_HINSTANCE hI
61566160
accelReg.translateAccel = translateAccel;
61576161
accelReg.isLocal = true;
61586162
accelReg.user = nullptr;
6159-
plugin_register("accelerator", &accelReg);
6163+
// Using "<accelerator" causes this to be placed at the front of the
6164+
// accelerator list, giving it the first chance to sniff keystrokes.
6165+
plugin_register("<accelerator", &accelReg);
61606166
return 1;
61616167

61626168
} else {

0 commit comments

Comments
 (0)