WebMIDI + knockout.js
by sfpgmr
HTML
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
<script src="http://sfpgmr.github.io/0002/scripts/undoredo.js"></script>
<h3>
MIDI入力データをモニタリングし、MIDI出力にスルーする。
</h3>
<div class="row">
<div class="col-md-4 col-sm-4">
<h4>Input Port Select</h4>
<select data-bind="options:inputs,optionsText:'name',value:input"></select>
</div>
<div class="col-md-4 col-sm-4">
<h4>Output Port Select</h4>
<select data-bind="options:outputs,optionsText:'name',value:output"></select>
</div>
</div>
<div>
<h4>Input Monitor</h4>
<table class="table table-condensed">
<thead>
<tr>
<th>time</th>
<th>event</th>
</tr>
</thead>
<!-- foreach バインディングを使用して MIDI イベントを表示 -->
<tbody data-bind="foreach:inputEvents" >
<tr>
<td data-bind="text:timeStamp"></td>
<!-- イベントデータはネストして表示 -->
<td data-bind="foreach:{data:$data.events,as:'ev'}">
<span><span data-bind="text:ev"></span> </span>
</td>
</tr>
</tbody>
</table>
</div>
JavaScript
// Modelデータ
function MIDI(access) {
var self = this;
self.access = access;
self.inputs = access.inputs();
self.outputs = access.outputs();
self.input = null;
self.output = null;
}
MIDI.prototype = {
selectInput: function (value) {
if(this.input !== value){
if (this.input) {
this.input.onmidimessage = null;
}
this.input = value;
var self = this;
this.input.onmidimessage =
function(ev){
if(ev.data[0] != 0xfe){
if(self.output){
self.output.send(ev.data,0);
}
$(self).trigger('midiEvent',[ev]);
}
};
}
},
selectOutput: function(value){
if(this.output !== value){
this.output = value;
}
}
};
// View Model
function ViewModel(midi) {
var self = this;
self.inputs = midi.inputs;
// 入力値の変化に応じてMIDI Modelをいじりたいのでcomputedを使用
self.input = ko.computed({
read: function () {
return midi.input;
},
write: function (value) {
midi.selectInput(value);
},
owner: this});
self.outputs = midi.outputs;
// 出力値の変化に応じてMIDI Modelをいじりたいのでcomputedを使用
self.output = ko.computed(
{
read: function(){return midi.output;},
write: function(value){ midi.selectOutput(value);},
owner:this
});
// MIDIイベントを保管する配列(10イベントまで)
self.inputEvents = ko.observableArray();
// MIDI Modelのイベント処理
$(midi).on('midiEvent',function(e,ev){
// イベントを文字列に変換
var evs = [];
for(var i = 0,end = ev.data.length;i < end;++i){
evs.push(('00' + ev.data[i].toString(16)).slice(-2));
}
// データ保存
self.inputEvents.push(
{
timeStamp: ev.receivedTime,
events:evs
}
...