nanoKEY2 Switcher - https://youtube.l8r.jp/MidiSwitcher.html
obs-websocket 4.9.1 - https://github.com/obsproject/obs-websocket/releases/tag/4.9.1
NanoKey.html
<!DOCTYPE html>
<html lang="ja"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<title>NanoKey</title><script>
$(e=>{
$('body').append($('<ul id="log">'))
var obs = new Switcher()
new NanoKey().message(e=>{
$('#log').prepend($('<li>').append(JSON.stringify(e)))
var i = 'CDEFGAB'.indexOf(e.note)
if(i>-1){
switch(e.type){
case 'NoteOn' :obs.switch(i);break
case 'NoteOff' :obs.switch(0);break
}
}
})
})
class NanoKey{
constructor(){
this.notes = 'C,C#,D,D#,E,F,F#,G,G#,A,A#,B'.split(',')
this.type = {0x80:'NoteOff',0x90:'NoteOn'}
this.hook = {}
this.message(e=>{})
navigator.requestMIDIAccess().then(r=>{
console.log(r)
r.inputs.forEach(v=>{
v.onmidimessage = e=>{
if(this.type[e.data[0]]) this.dispatch(...e.data)
}
})
},console.log)
}
message(f){this.hook.message = f;return this}
dispatch(type,noteNumber,velocity){
var n = this.notes[noteNumber%12]
var o = Math.floor(noteNumber/12)-1
this.hook.message({
type : this.type[type],
note : n,
octave : o,
key : n+o,
code : noteNumber,
})
}
}
class Switcher{
constructor(url){
this.scenes = []
this.history = {}
var w = this.client = new WebSocket(url||'ws://localhost:4440/')
w.onopen = e=>{
this.send(new Switcher.GetSceneList().then(r=>{
if(r.status=='ok') this.scenes = r.scenes
}))
}
w.onmessage = e=>{
var v = JSON.parse(e.data)
if(this.resolve(v)) e.stopImmediatePropagation()
}
}
switch(i){
if(this.connecting==false) return this
if(this.scenes[i]==null) return this
return this.send(new Switcher.SetCurrentScene(this.scenes[i]))
}
send(e){
if(this.connecting==false) return this
this.history[e['message-id']] = e
this.client.send(JSON.stringify(e))
return this
}
resolve(e){
var k = e['message-id']
if(this.history[k]==null) return false
this.history[k].resolve(e)
delete this.history[k]
return true
}
get connecting(){
if(this.client==null) return false
return this.client.readyState==WebSocket.OPEN
}
}
Switcher.Request = class SwitcherRequest{
constructor(e){
this['message-id'] = this.random()
Object.assign(this,e)
}
then(f){this.resolve=f;return this}
resolve(){}
random(){return Math.random().toString(36).substring(2)}
}
Switcher.GetSceneList = class extends Switcher.Request{
constructor(){super({
'request-type' : 'GetSceneList'
})}
}
Switcher.SetCurrentScene = class extends Switcher.Request{
constructor(v){super({
'request-type' : 'SetCurrentScene',
'scene-name' : v.name,
})}
}
</script>
</head></html>