Search code examples
clojureclojurescript

How do I make an object returned by the browser globally available then set a function as a property?


I am trying to access MIDI inputs in a ClojureScript project, using something like, in JS:

if (navigator.requestMIDIAccess) {
 console.log('WebMIDI is supported in this browser.');
 navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure);

I figured out how to get this to work with the Promesa library do! capability... however, the returned object, in JS, has a list of MIDI inputs, and one needs to set a function as the value of the 'onmidimessage' property of the inputs you care about. In JS this would look like this:

function onMIDISuccess(midiAccess) {
  var inputs = midiAccess.inputs;
  for (var input of midiAccess.inputs.values()) {
  input.onmidimessage = getMIDIMessage;
 }}

In JS, getMIDIMessage will be called whenever a MIDI message comes in. How do I set a function as the value of the 'onmidimessage' property of the return value of navigator.requestMIDIAccess so that it will be called properly?

I tried variations of set! and aget and neither work. Perhaps I'm incorrectly or not setting the 'midiAccess' object globally... not sure.

UPDATE: overcame embarrassment and added my attempt:

  (ns miditest.midi)

  (defn onMIDISuccess [midiAccess]
    (let [inputs (.values (.-inputs midiAccess))]
    (js/console.log (first inputs))))

  (defn onMIDIFailure []
    (js/console.log "this browser does not support WebMIDI."))

  (defn getMIDIMessage [message]
    (let [command (first (.data message))
        note (nth (.data message) 1)
        velocity (nth (.data message) 2)]
    (js/console.log (str command note velocity))))

  (defn checkmidi []
    (-> (.requestMIDIAccess js/navigator)
      (.then #(onMIDISuccess %))
      (.catch #(onMIDIFailure))
      (.finally #(js/console.log "cleanup"))))

I'm not sure the .catch will work as I'm not sure how to get .requestMIDIAccess to fail.


Solution

  • You can use set!.

    (defn getMIDIMessage [message]
      ...)
    
    (defn onMIDISuccess [midiAccess]
      (-> midiAccess
          .-inputs
          (.forEach (fn [input key]
                      (set! input -onmidimessage getMIDIMessage)))))