package nl.astraeus.vst.chip.midi import kotlinx.browser.window import nl.astraeus.vst.chip.audio.VstChipWorklet import nl.astraeus.vst.chip.view.MainView import org.khronos.webgl.Uint8Array import org.khronos.webgl.get external class MIDIInput { val connection: String val id: String val manufacturer: String val name: String val state: String val type: String val version: String var onmidimessage: (dynamic) -> Unit var onstatechange: (dynamic) -> Unit fun open() fun close() } external class MIDIOutput { val connection: String val id: String val manufacturer: String val name: String val state: String val type: String val version: String fun send(message: dynamic, timestamp: dynamic) fun open() fun close() } object Midi { var outputChannel: Int = -1 var inputs = mutableListOf() var outputs = mutableListOf() var currentInput: MIDIInput? = null var currentOutput: MIDIOutput? = null fun start() { val navigator = window.navigator.asDynamic() navigator.requestMIDIAccess().then( { midiAccess -> val inp = midiAccess.inputs val outp = midiAccess.outputs console.log("Midi inputs:", inputs) console.log("Midi outputs:", outputs) inp.forEach() { input -> console.log("Midi input:", input) inputs.add(input) console.log("Name: ${(input as? MIDIInput)?.name}") } outp.forEach() { output -> console.log("Midi output:", output) outputs.add(output) } MainView.requestUpdate() }, { e -> println("Failed to get MIDI access - $e") } ) } fun setInput(input: MIDIInput?) { console.log("Setting input", input) currentInput?.close() currentInput = input currentInput?.onstatechange = { message -> console.log("State change:", message) } currentInput?.onmidimessage = { message -> val data = message.data as Uint8Array val hex = StringBuilder() for (index in 0 until data.length) { hex.append(data[index].toString(16)) hex.append(" ") } console.log("Midi message:", hex) VstChipWorklet.postMessage( message.data ) } currentInput?.open() } fun setOutput(output: MIDIOutput?) { console.log("Setting output", output) currentOutput?.close() currentOutput = output currentOutput?.open() } fun send(data: Uint8Array, timestamp: dynamic = null) { currentOutput?.send(data, timestamp) } }