この文書は、W3Cの文書 "「Web MIDI API」 W3C Working Draft 16 November 2024" の日本語訳です。
旧版はこちら :Web MIDI APIの正式な文書は英語版のみであり、日本語訳には翻訳に起因する誤りが含まれている場合があります。
正式な文書はhttp://www.w3.org/TR/webmidi/にあります。
翻訳元の文書はまだワーキングドラフト(Working Draft)です。現状ではまだ説明が不足している部分があったり、今後も頻繁に更新される可能性がある事に注意してください。
日本語訳GitHub : https://github.com/g200kg/web-midi-api-ja
日本語訳公開URL : http://g200kg.github.io/web-midi-api-ja/
Tatsuya Shinyagaito @ g200kg
誤りその他があればGitHubページ、下のサイト経由などで連絡をお願いいたします。
http://www.g200kg.com/
2024年11月27日
Copyright © 2015-2024 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
シンセサイザー、キーボード等のコントローラー、ドラムマシンなど、 ユーザーエージェントはそのホストコンピューターやデバイスに接続された音楽機器を持っている場合があります。 広く採用されている、Musical Instrument Digital Interface (MIDI) プロトコルは電子楽器、 コントローラー、コンピューター間で相互に通信と同期を可能にするものです。 MIDI はオーディオ信号は送信しません: その代わりに音符に関するイベントメッセージ、音量やビブラートやパンニングなどのパラメーターのコントローラー信号、 キューやテンポを合わせるためのクロック、あるいはそのシステム固有の (例えばリモートに保存されているシンセサイザー固有のパッチデータなど) 通信を行います。 このプロトコルは照明装置や特殊効果の制御を行うショーコントロールのような、音楽以外での分野でも標準となっています。
この仕様は MIDI プロトコルをサポートする API を定義し、Web アプリケーションがクライアントシステム上の MIDI 入出力デバイスを列挙、選択し、MIDI メッセージ を送信および受信する事を可能にします。 ユーザーのシステム上にある MIDI デバイス への低レベルアクセスが可能になる事によって、音楽に関するものだけでなく、 非音楽関係の MIDI アプリケーションも構築できるようになります。 一方で Web MIDI API は、音楽やコントローラーの入力の意味を表現するものではありません; これは MIDI 入力と出力インターフェースのメカニズムに触れる事ができ、 MIDI メッセージ をその動作の意味を認識する事なく、送信および受信するという実用的な側面のために設計されています (例えば、"20Hz でビブラートを掛ける" や "G#7 の和音を演奏する" と言うような、 コントローラーの値が変わった事や G#7 の和音を演奏した時の一組のノートオンメッセージという以上の意味を持ちません)。
ユーザーの一部では、"MIDI" は、スタンダード MIDI ファイルおよびジェネラル MIDI と同義語として使われています。 それはこの API の意図する所ではありません; 単純に .SMF ファイルを再生する、という使用例はこの仕様の範囲ではありません (それは例えば HTML の audio
要素のような異なったフォーマットのものとしては考慮されるかも知れません)。 Web MIDI API は MIDI に対応するデバイス、例えば外部のシンセサイザーや照明システムへの直接的なアクセスを可能にする事を意図しています。 Web MIDI API はまた明らかに、MIDI コントローラーからの入力に反応するという新種の Web 上のアプリケーションを可能にするために設計されています。 Webアプリケーションを制御するために、(キーボード、ギター、管楽器コントローラーなどの楽器コントローラーとー同様に) 物理的なボタンやツマミやスライダーなどを使った、外部ハードウェアコントローラーが使用される事になるでしょう。
Web MIDI API はまた、Web プラットフォームの他の API や要素、特に Web Audio API と組み合わせて使われる事を想定しています。 また、この API は Apple 社の CoreMIDI や Microsoft 社の Windows MIDI API など、他のシステムの MIDI API のユーザーにとって親しみ安いように意図されています。
このセクションは、この文書の公開時における状況を記述したものです。 現在の W3C の刊行物およびこの技術レポートの最新版のリストは、 https://www.w3.org/TR/にある、W3C technical reports index から見つけることができます。
この文書は Audio Working Group によって Recommendation track を使用してワーキングドラフトとして公開されました。
ワーキングドラフトとしての公開は W3C およびそのメンバーによる承認を意味するものではありません。 これは草案文書であり、いつでも他の文書によって改訂、置き換えあるいは廃止される可能性があります。 この文書を作業中のもの以外として引用する事は不適切です。
この文書は W3C Patent Policy に基づいて運用されるグループによって作成されました。 W3C はグループの成果物から作成された特許開示リストを維持しており、そのページでは特許開示の手順についても提示しています。特許について実際の知識を持ち、 それが基本的な請求事項を含むと考える者は、W3C Patent Policy 6 節に従って情報を開示しなくてはなりません。
この文書は2023年11月03日 W3C文書管理方法によって管理されます。
このセクションは非基準情報です
Web MIDI API 仕様は Web 開発者が MIDI デバイス、 例えば機器が接続されるハードウェア MIDI ポートや USB-MIDI 仕様をサポートした USB 機器などに対して列挙、操作、アクセスを行う手段を定義しています。 MIDI に対する Web API を持つ事で、Web アプリケーションは既存のソフトウェアやハードウェアのシンセサイザー、ハードウェアの音楽コントローラー、 照明システムやその他の MIDI で制御される機器/機械を使う事ができるようになります。 この API は広い範囲の使用例を念頭に定義されています。
このAPIが取るアプローチは Apple 社の CoreMIDI や Microsoft 社の Windows MIDI API に似ています; つまり、API は開発者がその上に有用な MIDI ソフトウェアを構築できるように、 MIDI の低レベルのソフトウェアプロトコルを表すように設計されていると言う事です。 API は開発者が入出力インターフェースを列挙し、MIDI メッセージを送受信する事を可能にしますが、 (前述の他の API と同様に) 現存するデバイスを確実にサポートするために必要な範囲を超えて、MIDI メッセージ の意味を定義したり解釈する事は行いません。
Web MIDI API はシーケンサーなどの高レベルの概念を直接実装する事は意図していません; 例えば、スタンダード MIDI ファイルは直接サポートされませんが、Web MIDI API の上にスタンダード MIDI ファイルプレーヤーを構築する事は可能です。 また、ジェネラル MIDI が行っているようにパッチやコントローラーのアサインを意味的に定める事も意図しません; それらの解釈は Web MIDI API の範囲外です (繰り返しになりますが、Web MIDI API を通してジェネラル MIDI を簡単に利用する事はできます)。
この仕様中、非基準情報と書かれているセクションと同様に、全てのオーサリングガイドライン、図、例、注、は非基準情報です。 仕様内のその他の全ては基準情報です。
この文書内の MUST、SHOULD がこのように大文字で書かれている場合は BCP 14 [RFC2119] [RFC8174] で規定されているように解釈されます。
この仕様で定義される準拠の基準は、このインターフェースを実装するユーザーエージェント単体に適用されます。
この仕様で定められている API の実装に ECMAScript を使用する場合、この仕様で使用されている Web IDL 仕様 [WEBIDL] で定義される ECMAScript バインディングの作法で実装しなくてはなりません (MUST)。
Web Audio API およびそれに関連するインターフェース、概念は [webaudio] で定義されています。
MIDI、MIDI デバイス、MIDI 入力ポート、MIDI 出力ポート、MIDI インターフェース、MIDI メッセージ、システムリアルタイム、システムエクスクルーシブという用語は [MIDI] で定義されています。
8
、9
、A
、B
、E
のどれかならば、メッセージ全体の長さは 3 バイトです。C
または D
ならばメッセージ全体の長さは 2 バイトです。F1
または F3
ならばメッセージ全体の長さは 2 バイトです。F2
ならばメッセージ全体の長さは 3 バイトです。F6
、F8
、FA
、FB
、FC
、FE
、FF
のどれかならばメッセージ全体の長さは 1 バイト (ステータスバイトのみ) です。F0
ならばこれは長さの制限がないシステムエクスクルーシブメッセージであり、最終バイトは F7
になります。F4
、F5
、F7
、F9
、FD
のどれかならばこのメッセージは有効ではありません。Web Midi API は、"midi" という名前で識別される強力な機能です。次の権限関連のフラグを定義することで、パーミッションに統合されます。
WebIDLdictionary MidiPermissionDescriptor
: PermissionDescriptor {
boolean sysex
= false;
};
{name: "midi", sysex: true}
は {name:
"midi", sysex: false}
よりも強力
Web Midi API は、デフォルトの許可リストが "self"
である "midi" という名前のポリシー制御機能を定義します。
WebIDL[SecureContext, Exposed=(Window,Worker)] interface MIDIInputMap
{
readonly maplike <DOMString, MIDIInput
>;
};
MIDIInputMap
は、値が MIDIInput
のインスタンスで、キーはその ID になっているマップ風のインターフェースです。
この型は現在使用可能なすべての MIDI 入力ポートを表すのに使用されます。これにより、次の書き方を可能にします :
// to tell how many entries there are:
let numberOfMIDIInputs = inputs.size;
// add each of the ports to a <select> box
inputs.forEach( function( port, key ) {
let opt = document.createElement("option");
opt.text = port.name;
document.getElementById("inputportselector").add(opt);
});
// or you could express in ECMAScript 6 as:
for (let input of inputs.values()) {
let opt = document.createElement("option");
opt.text = input.name;
document.getElementById("inputportselector").add(opt);
}
WebIDL[SecureContext, Exposed=(Window,Worker)] interface MIDIOutputMap
{
readonly maplike <DOMString, MIDIOutput
>;
};
MIDIOutputMap
は値が MIDIOutput
のインスタンスで、キーがその ID になっているマップ風のインターフェースです。
この型は現在使用可能なすべての MIDI 出力ポートを表すのに使用されます。これにより、次の書き方を可能にします :
// to tell how many entries there are:
let numberOfMIDIOutputs = outputs.size;
// add each of the ports to a <select> box
outputs.forEach( function( port, key ) {
let opt = document.createElement("option");
opt.text = port.name;
document.getElementById("outputportselector").add(opt);
});
// or you could express in ECMAScript 6 as:
for (let output of outputs.values()) {
let opt = document.createElement("option");
opt.text = output.name;
document.getElementById("outputportselector").add(opt);
}
このインターフェースは MIDI 入力および出力デバイスをリストアップして、 それぞれのデバイスへのアクセスを得るためのメソッドを持ちます。
WebIDL[SecureContext, Exposed=(Window,Worker), Transferable] interface MIDIAccess
: EventTarget {
readonly attribute MIDIInputMap
inputs
;
readonly attribute MIDIOutputMap
outputs
;
attribute EventHandler onstatechange
;
readonly attribute boolean sysexEnabled
;
};
inputs
outputs
onstatechange
新しいポートが接続された、あるいは既存のポートの state 属性が変化した時に呼ばれるハンドラーです。
このイベントハンドラーは、MIDIConnectionEvent
型に対応し、 MIDIAccess
インターフェースを実装した全てのオブジェクトでサポートされなくてはなりません (MUST)。
このオブジェクトに EventHandler
をアタッチしたままにしておくと、ガベージコレクションが行われない事に注意が必要です。MIDIAccess
の使用が終了したら、onstatechange
リスナーをすべて削除する必要があります。
ユーザーエージェントは、これまで有効でなかった MIDI ポートが有効になった時、あるいは既存のポートの state 属性が変化した時にはいつでも、 次のステップを実行しなくてはなりません(SHOULD) :
MIDIPort
を port とします。MIDIConnectionEvent
の port
を port に設定し、MIDIAccess
で "statechange" という名前のイベントを発行します。sysexEnabled
このインターフェースは MIDI 入力または出力ポートを表します。
WebIDL[SecureContext, Exposed=(Window,Worker)] interface MIDIPort
: EventTarget {
readonly attribute DOMString id
;
readonly attribute DOMString? manufacturer
;
readonly attribute DOMString? name
;
readonly attribute MIDIPortType
type
;
readonly attribute DOMString? version
;
readonly attribute MIDIPortDeviceState
state
;
readonly attribute MIDIPortConnectionState
connection
;
attribute EventHandler onstatechange
;
Promise <MIDIPort
> open
();
Promise <MIDIPort
> close
();
};
id
ポートのユニーク ID です。 開発者はこれを、ユーザーがアプリケーション内で選択したポートを記憶しておくために使用できます。 ユーザーエージェントは id
がそのポートだけのユニークなものである事を保証しなくてはなりません (MUST)。 ユーザーエージェントはその id がアプリケーションのインスタンスをまたいで、 例えば、システムがリブートした時、 デバイスがシステムから取り外された時にも維持される事を保証しなくてはなりません (SHOULD)。 アプリケーションは MIDI 設定を再現するため、これらの id をローカルにキャッシュしようとするかも知れません。 システムによっては完全に永続的なユニーク性を持つ識別手段をサポートしていないかも知れず、 そのような場合、別のインターフェースが接続されたりシステムから切断された時に識別を維持し続けるのは難易度が高くなるでしょう (これによって要求されたポートのインデックスがずれるかも知れません)。 システムは MIDI API のインスタンスをまたいだポートのマッチングに最善の方法を取る事が期待されます: 例えばある実装ではポートインターフェースの製造者、名前、インデックスを何らかの形で使用したハッシュを id とし、ポートが接続された時にポートの id が一致するものを参照するかも知れません。 アプリケーションは MIDIPort の id の比較を品質のテストのために使用するかも知れません。
manufacturer
ポートの製造者名です。
name
ポートのシステム名です。
type
そのポートが入力ポートか出力ポートかを区別する識別子です。 MIDIOutput
の場合、これは "output"
にならなくてはなりません (MUST)。 MIDIInput
の場合、これは "input"
にならなくてはなりません (MUST)。
version
ポートのバージョンです。
state
connection
onstatechange
存在するポートの状態または接続の状態が変化した時に呼び出されるハンドラーです。
この "statechange" 型のイベントハンドラーは MIDIPort
インターフェースを実装するすべてのオブジェクトでサポートされなくてはなりません (MUST)。
このオブジェクトに EventHandler
をアタッチしたままにしておくと、ガベージコレクションが行われない事に注意が必要です。MIDIPort
の使用が終了したら、onstatechange
リスナーをすべて削除する必要があります。
open
MIDIPort
に対応する MIDI デバイスを明示的に使用可能にします。 この呼び出しは MIDIPort
を使用するために必須のものではない事に注意してください - MIDIOutput
での send()
の呼び出し、または MIDIInput
に MIDIMessageEvent ハンドラーを設定する事で暗黙的に open() を実行する 事ができます。 下層の実装はこの呼び出しに対して何もする必要がないかも知れません。 しかしながら下層の実装によっては MIDI デバイスへの共有アクセスをサポートしていないかも知れないため、 明示的な open() および close() 呼び出しを使う事で MIDI アプリケーションがデバイスへの排他アクセスを予想して制御する事が可能になります。
呼び出された時、このメソッドは与えられたユーザーシステムの MIDI ポートへのアクセス要求を表す Promise オブジェクトを返します。
もしそのポートが "connected" 状態であってポートへのアクセスが取得できれば (そしてそのポートで入出力が可能になれば)、Promise はリゾルブされます。
connected 状態のポートへのアクセスができなかった場合 (例えば、排他的アクセスシステムのプラットフォームでそのポートが既に使用中になっていた場合)、Promise は(設定されていれば) リジェクトが起動されます。
もし "disconnected" 状態のポートに対して open()
が呼び出された場合、 そのポートの .connectionは ポートが "connected" 状態に移行するかすべての参照が無くなるまで、 "pending" に遷移します。
このメソッドが呼び出された時、ユーザーエージェントは MIDIPort オープンのアルゴリズムを実行します (MUST):
新しい Promise オブジェクト、promise を作成し、結び付けられるリゾルバーを resolver とします。
promise を返却し、以下のステップを非同期的に実行します。
port を与えられた MIDIPort
オブジェクトとします。
もしデバイスの状態が既に "open" の場合、(例えば この MIDIPort
の open() が既に呼ばれている、または暗黙的にオープンされている場合)、 下の 成功 ラベルのステップにジャンプします。
もしデバイスの状態が "pending" の場合 (例えば既にオープンされ、その後デバイスが切断されている場合)、下の 成功 ラベルのステップにジャンプします。
もしデバイスの状態が "disconnected" の場合、MIDIPort
の connection
属性は "pending" に変化し、 新しい MIDIConnectionEvent
が MIDIAccess
の statechange ハンドラーと MIDIPort
の statechange ハンドラーに発行され、 下の 成功 ラベルのステップにジャンプします。
システム内の MIDI デバイスへのアクセスの取得を試みます。 もしそのデバイスが使用不能の場合 (例えば、既に他のプロセスで使用されていてオープンできない、あるいは切断された場合) 下の 失敗 ラベルのステップにジャンプします。 もしそのデバイスが使用可能でアクセスを取得できた場合、次のステップを続けます。
MIDIPort の connection
属性を "open"
に変更し、新しい MIDIConnectionEvent
を MIDIAccess
の statechange ハンドラーと MIDIPort
の statechange ハンドラーのキューに追加します。
このポートが出力ポートであり、送信を待機している保留中のデータがある場合は、そのデータの送信を非同期で開始します。
成功 : resolver の accept(value)
メソッドを port を引数として呼び出します。
これらのステップの実行を終了します。
失敗 : error を新たな DOMException
とします。 この例外の .name はもしポートが使用不能の場合、"InvalidAccessError"
となります。
resolver の reject(value)
メソッドを error を引数として呼び出します。
close
MIDIPort
に対応する MIDI デバイスを明示的に使用不能にします (この後状態は "open" から "closed" になります)。 このメソッドの呼び出しが成功すると (新しいハンドラーの設定による暗黙的な open() にかかわらず) MIDI メッセージは MIDIInput
の MIDIMessageEvent ハンドラーに もう伝達されなく事に注意してください。
下層の実装はこの呼び出しに対して何もする必要がないかも知れません。 しかしながら下層の実装によっては MIDI デバイスへの共有アクセスをサポートしていないかも知れないため、明示的な close() 呼び出しは MIDI アプリケーションに他のアプリケーションにデバイスへのアクセス を取得する事が可能な事を保証します。
呼び出された時、このメソッドはユーザーのシステム上で指定の MIDI ポートへのアクセス 要求をあらわす Promise オブジェクトを返します。 ポートがクローズされた時、(つまり排他的なアクセスのシステムではそのポートが他のアプリケーションから使用可能になった時)、Promise はリゾルブされます。 もしポートが切断された場合、Promise はリジェクトされます。
close()
メソッドが呼ばれた時、ユーザーエージェントは以下の手順を実行します (MUST) :
promise を新たな Promise オブジェクトとし、resolver をそれに対応するリゾルバーとします。
promise を返却し、以下のステップを非同期に実行します。
port を与えられた MIDIPort
オブジェクトとします。
もし、ポートが既に閉じられている (その .connection が "closed" - 例えばそのポートがまだ暗黙的にも明示的にもオープンされていない、あるいはこの MIDIPort
で close()
が既に呼ばれている)場合、下の closed ラベルに飛びます。
もしそのポートが入力ポートの場合、次のステップに進みます。 もし出力ポートで .state が "connected" で ない場合、すべての保留されている送信データをクリアし、次のステップに進みます。 タイムスタンプが未来のシステム内に保留されている送信データはすべてクリアし、タイムスタンプが過去または現在のすべての送信メッセージの送信を完了してから次のステップに進みます。
下層のシステムをオープンしているならポートへのアクセスをすべてクローズし、 下層システムのブロックしているリソースを解放します。
MIDIPort の connection
属性を "closed"
に変更し、新しい MIDIConnectionEvent
を MIDIAccess
の statechange ハンドラーおよび、MIDIPort
の statechange ハンドラーに発行します。
closed : resolver の accept(value)
メソッドを port を引数として呼び出します。
これらのステップの実行を終了します。
MIDIPort
に対応する MIDI ポートの state 属性が変化した時はいつでも、ユーザーエージェントは以下のステップを実行します (SHOULD) :
port を MIDIPort
とします。
MIDIConnectionEvent
の port
属性を port に設定し、MIDIPort
で statechange という名前のイベントと、MIDIAccess
で statechange という名前のイベントを発行します。
WebIDL[SecureContext, Exposed=(Window,Worker)] interface MIDIInput
: MIDIPort
{
attribute EventHandler onmidimessage
;
};
onmidimessage
このイベントハンドラーは "midimessage" 型であり、MIDIInput
インターフェースを実装する全てのオブジェクトでサポートされなくてはなりません (MUST)。
もしハンドラーが設定され、state 属性が "opened"
でない場合、下層の実装はポートを使用可能にして、state 属性を "opened"
に変更しようとします。 もし成功すれば MIDIConnectionEvent
イベントが対応する MIDIPort
と MIDIAccess
に対して発行されます。
MIDIInput
に対応する MIDI ポートが 1 つ以上の MIDI メッセージを受信完了した際にはいつでも、ユーザーエージェントは以下のステップを実行しなくてはなりません (MUST) :
port を MIDIInput
とします。
もし MIDIAccess
でシステムエクスクルーシブが有効でなく、そのメッセージがシステムエクスクルーシブの場合はこの手順を中断します。
timeStamp
属性をシステムがメッセージを受信した時刻とし、data
属性を単一の MIDI メッセージを表す MIDI データ バイトの Uint8Array
とした MIDIMessageEvent
を使用して、port に "midimessage" という名前のイベントを発行します。
特に注意を要するのは、入力ストリームの他のメッセージの途中で MIDI システムリアルタイムメッセージが発生した時です。 この場合、そのシステムリアルタイムメッセージは発生する度にディスパッチされ、通常のメッセージはそれが完結するまでバッファされます (その後ディスパッチされます)。
WebIDL[SecureContext, Exposed=(Window,Worker)] interface MIDIOutput
: MIDIPort
{
undefined send
(sequence<octet> data, optional DOMHighResTimeStamp timestamp = 0);
undefined clear
();
};
send
対応する MIDI ポートのキューに送信するメッセージを登録します。 下層の実装は (もし必要なら) シーケンスの各メンバーを強制的に unsigned 8 ビット整数にします。 Uint8Array でなくシーケンスを使う事で、開発者は output.send( new Uint8Array( [ 0x90, 0x45, 0x7f ] ));
のように Uint8Array を作る事なく、output.send( [ 0x90, 0x45, 0x7f ] );
のような便利な書き方ができます。
data は 1 つ以上の完結した有効な MIDI メッセージを含む事ができます。 下層のシステムがサポートしていない可能性があるのと同様、data 中にランニングステータスは使用できません。
もし、data が有効なシーケンスでない、あるいは有効な MIDI メッセージを含んでいない場合、TypeError
例外が発生します。
もし data がシステムエクスクルーシブメッセージで、MIDIAccess
がシステムエクスクルーシブへのアクセスが有効でない場合、InvalidAccessError
例外が発生します。
もしポートが "disconnected" 状態の場合、InvalidStateError
例外が発生します。
もしポートが "connected" 状態 であるが接続が "closed" の場合、非同期でポートのオープンを試みます。
DOMHighResTimeStamp
- ドキュメントへのナビゲーション開始からの相対時間でミリ秒で表されます)。 もし timestamp が存在しない場合、 または 0 (あるいは既に過ぎた時刻) を指定された場合、データは可能な限り即時に送信されます。
clear
MIDIOutput
のキューからまだ送られていないすべての保留中の送信データをクリアします。 実装は MIDI ストリームが正常な状態に維持される事を保証する必要があり、もし出力ポートが sysex メッセージの途中にあった場合は sysex を終端するバイト (0xf7) が送信されなくてはなりません。
WebIDLenum MIDIPortType
{
"input
",
"output
",
};
input
MIDIPort
が入力ポートの場合、type メンバーはこの値でなくてはなりません (MUST)。
output
MIDIPort
が出力ポートの場合、type メンバーはこの値でなくてはなりません (MUST)。
WebIDLenum MIDIPortDeviceState
{
"disconnected
",
"connected
",
};
disconnected
MIDIPort
が表すデバイスがシステムから切断されました。 デバイスがシステムから切断された場合、それは関連する入力や出力のマップには現れません。
connected
MIDIPort
が表すデバイスが接続され、入力および出力ポートのマップに現れます。
WebIDLenum MIDIPortConnectionState
{
"open
",
"closed
",
"pending
",
};
open
MIDIPort
が表すデバイスがオープンされ (暗黙的または明示的にかかわらず)、使用可能になりました。
closed
MIDIPort
表すデバイスがオープンされていません、あるいは明示的にクローズされました。 MIDIPort
が ( MIDIPort
.open
()
によって) 明示的にオープンされるか (入力ポートに対して midimessage イベントハンドラーが追加されるか、出力ポートに対して MIDIOutput
.send
()
を呼び出すことで) 暗黙的にオープンされるまで、これはデバイスのデフォルトの状態です。
pending
MIDIPort
が表すデバイスが (暗黙的にまたは明示的に) オープンされましたが、 デバイスはその後切断され使用できない状態です。 もしそのデバイスが statechange イベントより前に再接続されれば、 システムはデバイスの再オープンを (MIDIPort をオープンするアルゴリズムに従って) 試みなければなりません。 これによって接続状態は "open" または "closed" に遷移します。
MIDI メッセージを受信した時、このインターフェースを実装したイベントオブジェクトが、MIDIInput
の onmidimessage ハンドラーに渡されます。 DOM Event
の timeStamp
属性は DOMHighResTimeStamp
として定義されていて、イベントが受信または送信された時刻を高い分解能で表すことに注意してください。
WebIDL[SecureContext, Exposed=(Window,Worker)]
interface MIDIMessageEvent
: Event {
constructor
(DOMString type, optional MIDIMessageEventInit
eventInitDict = {});
readonly attribute Uint8Array? data
;
};
data
1 つの MIDI メッセージのデータのバイト列を含む Uint8Array です。
WebIDLdictionary MIDIMessageEventInit
: EventInit {
Uint8Array data
;
};
data
1 つの MIDI メッセージのデータのバイト列を含む Uint8Array です。
新しいポートが使用可能になった時、(例えば MIDI デバイスが最初にコンピューターに接続された時)、 以前使用可能だったポートが使用不能になった時、または再度使用可能になった時、 (例えば MIDI インターフェースが切断され、再度接続された時)、 このインターフェースを実装したイベントオブジェクトが MIDIAccess
の onstatechange
ハンドラーに渡されます。 また (もしあれば) そのポートを参照する全ての MIDIPort
の onstatechange
ハンドラー にも渡されます。
MIDIPort
が "pending" 状態にあり、そのデバイスがホストシステムに再接続された時は、statechange イベントが 発行される前に MIDIPort オープンのアルゴリズムが実行され、 再オープンを試みます。 もしこの遷移が失敗した場合は (例えばそのポートが下層システムの何かで予約され使用できないなど)、 接続状態は "closed" に遷移し、そうでなければ "open" に遷移します。 これはそのデバイスの状態変化の statechange イベント発行に先立って行わます。そのためイベントではデバイスの状態と同様に最終的な接続状態を反映します。
下層のシステムによってはデバイスの接続状態に関するイベントを提供しない場合があります。そのような システムでは新しいデバイスをまれにしかポーリングせず、大きなディレイが発生するかも知れません。 このような事情で、接続イベントに大きくは依存しないほうが良いでしょう。
WebIDL[SecureContext, Exposed=(Window,Worker)]
interface MIDIConnectionEvent
: Event {
constructor
(DOMString type, optional MIDIConnectionEventInit
eventInitDict = {});
readonly attribute MIDIPort
? port
;
};
port
接続または切断されたポートです。
WebIDLdictionary MIDIConnectionEventInit
: EventInit {
MIDIPort
port
;
};
port
接続または切断されたポートです。
ユーザーの MIDI インターフェースの列挙を可能にする事は潜在的にフィンガープリンティングのターゲットになります。 それは特定の MIDI インターフェースを接続する事によってユーザーを一意に識別するという意味です。
この文脈で注意するべきは、MIDI インターフェースの列挙である事です。 USB-MIDI デバイスの場合は典型的には、自身の MIDI インターフェイスを持っているために列挙され、USB でホストコンピュータに接続されているほとんどのデバイスがこれに含まれます。 個別のサンプラーやシンセサイザー等の 5 ピン DIN ケーブルで接続されている MIDI デバイスは列挙されません。フィンガープリントの対象となるインターフェースは MIDI "ポート" と同等であり、それぞれの MIDI インターフェースは API によって MIDI インターフェースに対する個別のデバイスの名前、製造者、その内容の詳細が不明な id、が露出します。
ほとんどのシステムでは MIDI インターフェースが接続されていません。大量の MIDI インターフェースを持っているシステムはあまり多くありません。したがって、MIDI デバイスの列挙による付加的なフィンガープリントの露出は、ゲームパッド API のゲームパッド列挙による付加的なフィンガープリントの露出に類似しています : 一般的なユーザーならばせいぜい数台のデバイスを接続し、その構成は変更される可能性があり、露出される情報はインターフェイス自体に関する情報です (つまり、ユーザーが構成したデータはありません)。
最初の MIDI デバイスは、Web プラットフォームとそのセキュリティ上のリスクが存在する前の 1983 年にリリースされました。 多くの MIDI デバイスは、メーカーがサポートを終了してからも長い間使用され続けています。 MIDI は本来のシリアル接続を超えて、FireWire、USB、Bluetooth などの伝送にも適応しています。 これにより、異なる時代のデバイスが正式にサポートされていないにもかかわらず、設計者が予想していなかった方法でコンピューターや Web に接続され、現在も積極的に使用されているため、セキュリティ上の課題が生じています。
懸念される攻撃として、理論的には USB-MIDI デバイスに対する悪意のあるファームウェアの更新があります。USB デバイスは一般的にその USB デバイス自身が送信するデバイス記述子に基づいて動作します。もし、USB-MIDI デバイスのファームウェアが記述子を書き換えられるなら自身をヒューマンインタフェースデバイスとする事が可能です。これにより、悪意のある Web サイトからのキーボードの入力の読み取りや挿入、あるいはシステムの完全な侵害に繋がります。
攻撃は以下のように進められます :
上記の攻撃を可能にするには、MIDI デバイスが以下の条件を すべて 満たしている必要があります。
悪意のあるファームウェア更新に対して脆弱であっても、他の条件を満たしていない MIDI デバイスは、この攻撃でホストシステムを侵害するために使用することはできません。悪意のあるファームウェア更新によって、これらの MIDI デバイスが動作を停止したり、望ましくない動作をしたりする可能性はあります。
このリスクを軽減するため、実装者は実装の際に次の点を重視しなくてはなりません :
requestMIDIAccess()
のアクセス許可プロンプトの文言などで、ファームウェア更新のリスクをユーザーに通知する方法で実装します。既知の MIDI デバイスのリストにより明示的に許可またはブロックすることも、この特殊な攻撃の軽減に貢献するかも知れませんが、多くの小さな企業や個人が MIDI デバイスを開発しており、多くの MIDI デバイスが既にサポートされていないため、これを行うと Web MIDI API の使いやすさが大幅に低下するかもしれません。
利用可能なポートを識別するフィンガープリントの問題とは別に、MIDI メッセージの送受信に関する問題もあります。これらの問題については、以下でさらに詳しく説明します。
MIDI メッセージは、システムエクスクルーシブメッセージと、ショート (非システムエクスクルーシブな) メッセージに分けられます。システムエクスクルーシブメッセージは更に、一般的に認知されている MIDI タイムコードや MIDI サンプルダンプスタンダードなどのユニバーサルシステムエクスクルーシブメッセージと、他のデバイスには適用されない "Roland Jupiter-80 シンセサイザー用のパッチコントロールデータ" などのデバイス固有メッセージにさらに分けられます。
セキュリティ上の懸念について議論する前に、これらの機能を使用して MIDI でどのようなシナリオが可能かを調べると役立ちます :
それぞれの潜在的なセキュリティへの影響は次のとおりです :
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: