midk
Version:
Mapping MIDI keypress to PC keyboard
88 lines (68 loc) • 1.94 kB
text/typescript
import signale from './signale'
import {
MessageStatus,
NoteCode,
} from './midi'
import { KeypressHandler } from './readMIDI'
import {
mergePortalFn,
} from './portal'
import { MidkConfig } from './configParser'
import { noteToSendKey } from './sendKey'
import { ToggleKeys, PressedNotes, isSetEqual } from './handlerType'
export const genNoteHandler = (config: MidkConfig): {
playModeToggleKeys: ToggleKeys,
pressedNotes: PressedNotes,
noteHandler: KeypressHandler,
} => {
const { playMode, portal, fnPortal } = config
const playModeToggleKeys: ToggleKeys = new Set<NoteCode>(playMode.toggle)
const pressedNotes: PressedNotes = new Set<NoteCode>()
const noteHandler: KeypressHandler = ({
status: noteEvent,
channel: noteCode,
}) => {
const noteName = NoteCode[noteCode]
if (!noteName) {
signale.warn('[MIDI] [note] unknow key-code', {
status: MessageStatus[noteEvent],
noteCode,
})
return
}
const pressed = noteEvent === MessageStatus.noteOnEvent
signale.info('[MIDI] [note]', {
noteName,
pressed,
noteCode,
status: MessageStatus[noteEvent],
})
if (pressed) {
pressedNotes.add(noteCode)
if (isSetEqual(pressedNotes, playModeToggleKeys)) {
playMode.enable = !playMode.enable
signale.warn('[MIDI] playMode', playMode)
}
} else {
pressedNotes.delete(noteCode)
}
// playMode, skip keyboard control
if (playMode.enable) {
return
}
const fnPressed = [...pressedNotes].filter(note => note in fnPortal)
if (fnPressed.length > 0) {
signale.info('[MIDI] Fn note pressed:', fnPressed.map(note => NoteCode[note]))
}
noteToSendKey({
noteCode,
pressed,
portal: mergePortalFn(portal, fnPressed.map(note => fnPortal[note])),
})
}
return {
playModeToggleKeys,
pressedNotes,
noteHandler,
}
}