UNPKG

midk

Version:

Mapping MIDI keypress to PC keyboard

83 lines (67 loc) 2.25 kB
// https://github.com/justinlatimer/node-midi import midi from 'midi' import { Message, MessageData, MessageStatus, Timestamp } from './midi' import signale from './signale' export interface KeypressParams { status: MessageStatus, channel: MessageData, value?: MessageData, timestamp?: Timestamp, } // return true to stop processing export type KeypressHandler = (keypress: KeypressParams) => void | boolean export const retryTimes = Infinity export const retryInterval = 3000 export const sleep = (ms = 1000) => new Promise<void>( (resolve) => setTimeout(() => resolve(), ms), ) export const handlersMap = new Map<MessageStatus, Set<KeypressHandler>>() export const regHandler = (status: MessageStatus, handler: KeypressHandler) => { const handlers = handlersMap.get(status) if (handlers) { handlers.add(handler) return } handlersMap.set(status, new Set([handler])) } export const removeHandler = (status: MessageStatus, handler: KeypressHandler) => { const handlers = handlersMap.get(status) handlers.delete(handler) } export const cleanHandlers = (status: MessageStatus) => { handlersMap.set(status, new Set()) } export const startListener = async () => { const input = new midi.Input() for (let i = 1; i <= retryTimes; i++) { // Count the available input ports. if (input.getPortCount() > 0) { break } signale.warn(`Cannot find MIDI input device, waiting for retry. (${i}/${retryTimes})`) await sleep(retryInterval) } if (input.getPortCount() < 1) { signale.error('Failed to find MIDI input device') process.exit(1) return } // Get the name of a specified input port. // 0: first device input.getPortName(0) input.on('message', (timestamp: Timestamp, message: Message) => { const [status, channel, value] = message signale.info('[MIDI]', { message, timestamp, }) const handlers = handlersMap.get(status) ?? new Set() signale.info('[MIDI] find handlers', [...handlers].map(fun => fun.name)) for (let handler of handlers) { if (handler({ status, channel, value, timestamp })) break } }) // Open the first available input port. input.openPort(0) signale.info('[MIDI] started listening') }