MIDI In: ⟹ MIDI Out:
Redirect input from selected MIDI-In to selected MIDI-Out.
<!DOCTYPE html>
<html>
<head>
<title>Select MIDI</title>
<script src="JZZ.js"></script>
<script src="JZZ.synth.Tiny.js"></script>
<script src="JZZ.input.Kbd.js"></script>
<style type="text/css">
.inner {position:absolute; bottom:0; left:0; width:100%; text-align:center;}
select {width:15em;}
</style>
</head>
<body>
<h1>Select MIDI</h1>
<p>
MIDI In: <select id=selectmidiin></select> ⟹
MIDI Out: <select id=selectmidiout></select>
</p>
<p id=piano><p>
<script><!--
var selectMidiIn = document.getElementById('selectmidiin');
var selectMidiOut = document.getElementById('selectmidiout');
var midiInName = 'HTML Piano';
var midiOutName = 'Not available';
var midiInPort;
var midiOutPort;
function setListbox(lb, s) {
for (var i = 0; i < lb.options.length; i++) if (lb.options[i].value == s) lb.options[i].selected = 1;
}
JZZ.synth.Tiny.register('Web Audio');
var ascii = JZZ.input.ASCII({Z:'C5', S:'C#5', X:'D5', D:'D#5', C:'E5', V:'F5', G:'F#5', B:'G5', H:'Ab5', N:'A5', J:'Bb5', M:'B5'});
var piano = JZZ.input.Kbd({at: 'piano', from: 'C5', to: 'B5', onCreate: function(){
this.getBlackKeys().setStyle({color:'#fff'});
this.getKey('C5').setInnerHTML('<span class=inner>Z</span>');
this.getKey('C#5').setInnerHTML('<span class=inner>S</span>');
this.getKey('D5').setInnerHTML('<span class=inner>X</span>');
this.getKey('D#5').setInnerHTML('<span class=inner>D</span>');
this.getKey('E5').setInnerHTML('<span class=inner>C</span>');
this.getKey('F5').setInnerHTML('<span class=inner>V</span>');
this.getKey('F#5').setInnerHTML('<span class=inner>G</span>');
this.getKey('G5').setInnerHTML('<span class=inner>B</span>');
this.getKey('G#5').setInnerHTML('<span class=inner>H</span>');
this.getKey('A5').setInnerHTML('<span class=inner>N</span>');
this.getKey('A#5').setInnerHTML('<span class=inner>J</span>');
this.getKey('B5').setInnerHTML('<span class=inner>M</span>');
}});
ascii.connect(piano);
midiInPort = piano;
var through = JZZ.Widget();
function onMidiOutSuccess() {
if (midiOutPort) {
midiOutPort.close();
}
midiOutPort = this;
through.connect(this);
midiOutName = this.name();
setListbox(selectMidiOut, midiOutName);
}
function onMidiOutFail() {
if (midiOutPort) through.connect(midiOutPort);
setListbox(selectMidiOut, midiOutName);
}
function onMidiInSuccess() {
if (midiInPort && midiInPort != piano) {
midiInPort.close();
}
midiInPort = this;
this.connect(through);
midiInName = this.name();
setListbox(selectMidiIn, midiInName);
}
function onMidiInFail() {
if (midiInPort) midiInPort.connect(through);
setListbox(selectMidiIn, midiInName);
}
JZZ().and(function(){
var i;
for (i = 0; i < this.info().outputs.length; i++) {
selectMidiOut[i] = new Option(this.info().outputs[i].name);
}
if (!i) {
selectMidiOut[i] = new Option('Not available');
}
for (i = 0; i < this.info().inputs.length; i++) {
selectMidiIn[i] = new Option(this.info().inputs[i].name);
}
selectMidiIn[i] = new Option('HTML Piano');
selectMidiIn[i].selected = 1;
});
JZZ().openMidiOut().or(onMidiOutFail).and(onMidiOutSuccess);
JZZ().openMidiIn().or(onMidiInFail).and(onMidiInSuccess);
function changeMidiIn() {
var name = selectMidiIn.options[selectMidiIn.selectedIndex].value;
if (name == midiInName) return;
if (midiInPort) midiInPort.disconnect(through);
if (name == 'HTML Piano') {
if (midiInPort) midiInPort.close();
midiInPort = piano;
midiInPort.connect(through);
midiInName = name;
}
else JZZ().openMidiIn(name).or(onMidiInFail).and(onMidiInSuccess);
}
function changeMidiOut() {
var name = selectMidiOut.options[selectMidiOut.selectedIndex].value;
if (name == midiOutName) return;
if (midiOutPort) through.disconnect(midiOutPort);
JZZ().openMidiOut(name).or(onMidiOutFail).and(onMidiOutSuccess);
}
selectMidiIn.addEventListener('change', changeMidiIn);
selectMidiOut.addEventListener('change', changeMidiOut);
--></script>
</body>
</html>