Copyright © 2015-2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
一部のユーザーエージェントには、シンセサイザー、キーボードや その他のコントローラー、ドラムマシンなどの音楽デバイスが、ホストコンピューター またはデバイスに接続されている。広く採用されている Musical Instrument Digital Interface (MIDI) プロトコルは、電子楽器、コントローラー、 コンピューターが相互に通信し同期することを可能にする。MIDI は 音声信号を送信しない。代わりに、楽音の ノート、音量、ビブラート、 パンニングなどのパラメーターに対するコントローラー信号、テンポを設定するためのキューや クロック信号、およびシステム固有の MIDI 通信(例:シンセサイザー固有のパッチ データを遠隔で保存するための通信)に関するイベントメッセージを送信する。この同じプロトコルは、 ショー制御、照明、特殊効果制御など、 音楽以外の用途においても標準となっている。
この仕様は、MIDI プロトコルをサポートする API を定義し、 Web アプリケーションがクライアントシステム上の MIDI 入出力デバイスを列挙および選択し、 MIDI メッセージを送受信できるようにする。これは、 ユーザーのシステムで利用可能なMIDI デバイスへの低レベルアクセスを提供することで、 音楽向けの MIDI アプリケーションだけでなく、音楽以外の MIDI アプリケーションも可能にすることを 意図している。Web MIDI API は、音楽または コントローラー入力を意味論的に記述することを意図していない。これは、MIDI 入出力インターフェイスの 仕組み、およびMIDI メッセージの送受信に関する実際的な側面を公開するよう設計されており、 それらの動作が意味論的に何を意味し得るかを特定しない(例:「ビブラートを 20Hz 変調する」または「G#7 コードを演奏する」という観点ではなく、 コントローラー値を変更する、またはたまたま G#7 コードを表す ノートオンメッセージの集合を送信するという観点に限る)。
一部のユーザーにとって、「MIDI」は Standard MIDI Files
および General 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 公開文書の一覧およびこの技術報告の最新版は、 W3C 技術 報告インデックス( https://www.w3.org/TR/)で確認できる。
この文書は、Audio Working Group によって、 勧告トラックを使用した 作業草案として公開された。
作業草案としての公開は、 W3C およびその会員による支持を意味しない。
これは草案文書であり、いつでも他の 文書によって更新、置換、または廃止される可能性がある。この文書を 進行中の作業以外のものとして引用することは不適切である。
この文書は、 W3C Patent Policy の下で活動するグループによって作成された。 W3C は、そのグループの 成果物に関連して行われた特許開示の公開一覧を 維持している。そのページには、 特許を開示するための手順も含まれている。ある個人が、 その個人が 必須請求項を含むと考える特許について 実際の知識を有している場合、その個人は W3C Patent Policy のセクション 6に従って 情報を開示しなければならない。
この文書は、 2023年11月3日の W3C Process Document によって管理される。
このセクションは非規範的である。
Web MIDI API 仕様は、Web 開発者が MIDI デバイスを列挙、操作、およびアクセスするための手段を定義する。たとえば、 他のデバイスが接続されたハードウェア MIDI ポートを提供し得る インターフェイスや、USB-MIDI 仕様をサポートする USB デバイスである。MIDI のための Web API を持つことで、 既存のソフトウェアおよびハードウェアシンセサイザー、ハードウェア音楽 コントローラー、照明システム、および MIDI によって制御されるその他の機械装置を 使用する Web アプリケーションが可能になる。この API は、この幅広いユースケースを 念頭に置いて定義されている。
この API が採るアプローチは、Apple の CoreMIDI API および Microsoft の Windows MIDI API で採られているものと類似している。すなわち、この API は、 開発者がその上に強力な MIDI ソフトウェアを構築できるようにするため、 MIDI の低レベルなソフトウェアプロトコルを表現するよう設計されている。この API は、 開発者が入力および出力インターフェイスを列挙し、 MIDI メッセージを送受信できるようにするが、(前述の API と同様に) 現行のデバイスを堅牢にサポートするために必要な範囲を超えて、 MIDI メッセージを意味論的に定義または解釈しようとはしない。
Web MIDI API は、シーケンシングなどの高レベルな 概念を直接実装することを意図していない。たとえば Standard MIDI Files を直接サポートしないが、Standard MIDI File プレーヤーは Web MIDI API の上に構築できる。また、General MIDI が行うように、 パッチやコントローラー割り当てを意味論的に 捉えることも意図していない。そのような解釈は Web MIDI API の範囲外である (ただし、この場合も General MIDI は Web MIDI API を通じて容易に利用できる)。
非規範的であると示されたセクションに加えて、この仕様におけるすべての作成ガイドライン、図、例、および注記は 非規範的である。この仕様におけるそれ以外のすべては規範的である。
この文書におけるキーワード MUST および SHOULD は、 ここに示されているようにすべて大文字で現れる場合、かつその場合に限り、 BCP 14 [RFC2119] [RFC8174] に記述されているとおりに解釈される。
この仕様は、単一の 製品、すなわち、この仕様に含まれるインターフェイスを 実装するユーザーエージェントに適用される適合性基準を定義する。
ECMAScript を使用してこの仕様で定義される API を実装する 実装は、この仕様がその仕様および用語を使用しているため、 Web IDL 仕様 [WEBIDL] で定義される ECMAScript Bindings と整合する方法で それらを実装しなければならない(MUST)。
Web Audio API およびそれに 関連する インターフェイスと概念は [webaudio] で定義される。
用語 MIDI、MIDI デバイス、MIDI 入力 ポート、MIDI 出力ポート、MIDI インターフェイス、 MIDI メッセージ、System Real Time および System Exclusive は [MIDI] で定義される。
8、9、
A、B、または E の場合、メッセージ全体の長さは 3
バイトであるべきである
C または D の場合、
メッセージ全体の長さは 2 バイトであるべきであるF1 または F3 の場合、メッセージ全体の
長さは 2 バイトであるべきであるF2 の場合、メッセージ全体の長さは
3 バイトであるべきであるF6、F8、FA、FB、
FC、FE、
または FF の場合、メッセージ全体の長さは 1 バイト
(ステータスバイトのみ)であるべきである
F0 の場合、これは長さ制限のない System
Exclusive メッセージであり、最後の
バイトは F7 であるべきであるF4、F5、F7、F9、または
FD の場合、
メッセージは妥当ではない
Web Midi API は、強力な機能であり、 名前 "midi" によって識別される。これは、 次の権限関連フラグを定義することで、 Permissions と統合される:
WebIDLdictionary MidiPermissionDescriptor : PermissionDescriptor {
boolean sysex = false;
};
{name: "midi", sysex: true} は {name:
"midi", sysex: false} よりも強い。
Web Midi API は、
"midi" という名前のポリシー制御
機能を定義し、それは
'self' のデフォルト
許可リストを持つ。
WebIDL[SecureContext, Exposed=(Window,Worker)] interface MIDIInputMap {
readonly maplike <DOMString, MIDIInput>;
};
MIDIInputMap は、値が
MIDIInput インスタンスであり、キーがその ID である
maplike インターフェイスである。
この型は、現在利用可能なすべてのMIDI 入力 ポートを表すために使用される。
WebIDL[SecureContext, Exposed=(Window,Worker)] interface MIDIOutputMap {
readonly maplike <DOMString, MIDIOutput>;
};
MIDIOutputMap は、値が
MIDIOutput インスタンスであり、キーがその ID である
maplike インターフェイスである。
この型は、現在利用可能なすべてのMIDI 出力 ポートを表すために使用される。
このインターフェイスは、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とする。
MIDIAccess で "statechange"
という名前のイベントを発火し、
MIDIConnectionEvent を用い、port を port に設定する。
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
既存のポートがその state または connection 属性を変更したときに呼び出されるハンドラー。
このイベント
ハンドラーは、型 "statechange" であり、MIDIPort インターフェイスを実装するすべてのオブジェクトで
サポートされなければならない(MUST)。
このオブジェクトにEventHandler
を接続したままにすると、そのオブジェクトが
ガベージコレクトされなくなることを理解することが重要である。
MIDIPort の使用を終えたら、
すべての onstatechange リスナーを削除するべきである。
open
MIDIPort に対応するMIDI デバイスを
明示的に利用可能にする。この呼び出しは、
MIDIPort を使用するために必要ではないことに注意。
MIDIOutput で send() を呼び出すこと、
MIDIInput に MIDIMessageEvent EventHandler
を接続すること、または
MIDIInput に MIDIMessageEvent EventListener
を追加することにより、暗黙的な open() が発生する。基盤となる
実装は、この呼び出しに応答して何も行う必要がない場合がある。
しかし、一部の基盤となる実装は、MIDI デバイスへの共有アクセスを
サポートできない場合があるため、明示的な
open() および close() 呼び出しを使用することで、MIDI アプリケーションは
デバイスへのこの排他的アクセスを予測可能に制御できる。
呼び出されると、このメソッドは、ユーザーのシステム上の所与の MIDI ポートへの アクセス要求を表す Promise オブジェクトを返す。
ポートデバイスの state が "connected" である場合、 ポートへのアクセスが取得されると(そしてポートが入力または 出力の準備ができると)、提供された Promise は解決される。
接続済みポートへのアクセスが利用できない場合(たとえば、 排他的アクセスのみのプラットフォームでそのポートがすでに使用中である場合)、 Promise は拒否される(もしあれば)呼び出される。
open() が "disconnected" であるポートで呼び出された場合、
そのポートの
.connection は
"pending" に遷移し、
そのポートが "connected" になるか、それへのすべての参照が
破棄されるまで続く。
提供されたすべての Promise がまだ settle していなくても、
open() を複数回呼び出すことは許可される。
このメソッドが呼び出されたとき、ユーザーエージェントは MIDIPort を開くアルゴリズムを 実行しなければならない(MUST):
promise を新しい Promise オブジェクトとし、 resolver をそれに関連付けられた resolver とする。
promise を返し、次の手順を 非同期に実行する。
port を所与の MIDIPort オブジェクトとする。
デバイスの connection がすでに "open" である場合
(例:open() がすでにこの MIDIPort
で呼び出されている、またはポートが
暗黙的に開かれている場合)、下の success
とラベル付けされた手順へジャンプする。
デバイスの connection が "pending" である場合 (すなわち、connection は開かれていたが、その後デバイスが 切断された場合)、下の success とラベル付けされた手順へジャンプする。
デバイスの state が "disconnected" である場合、
MIDIPort の
connection 属性を
"pending" に変更し、新しい
MIDIConnectionEvent を
MIDIAccess の
statechange ハンドラーと、
MIDIPort の
statechange ハンドラーにキューイングし、下の
success
とラベル付けされた手順へジャンプする。
システム内の所与のMIDI デバイスへのアクセス取得を試みる。 デバイスが利用できない場合(例:別のプロセスによってすでに使用中であり 開けない、または切断されている場合)、 下の failure とラベル付けされた手順へジャンプする。デバイスが 利用可能でアクセスが取得された場合、次の手順を続行する。
MIDIPort の connection 属性を
"open" に変更し、新しい
MIDIConnectionEvent を
MIDIAccess の
statechange ハンドラーと、
MIDIPort の
statechange ハンドラーにキューイングする。
このポートが出力ポートであり、将来の timestamp を持つキュー済み送信データが ある場合、そのデータの送信を非同期に開始する。
success:resolver の
accept(value) メソッドを、port を
値引数として呼び出す。
これらの手順を終了する。
failure:error を新しい
DOMException
とする。
この例外の .name は、ポートが利用できない場合、
"InvalidAccessError" であるべきである。
resolver の reject(value) メソッドを、
error を値引数として呼び出す。
close
MIDIPort に対応するMIDI デバイスを
明示的に利用不可にする(その後、状態を
"open" から "closed" に変更する)。この
メソッドの呼び出しが成功すると、MIDIInput 上の
MIDIMessageEvent ハンドラーに
MIDI メッセージがもはや
配信されなくなることに注意(ただし、
新しいハンドラーを設定すると暗黙的な open() が発生する)。
基盤となる実装は、この呼び出しに応答して 何も行う必要がない場合がある。しかし、一部の基盤となる実装は MIDI デバイスへの共有アクセスをサポートできない場合があり、 明示的な close() 呼び出しにより、MIDI アプリケーションは 他のアプリケーションがデバイスへのアクセスを取得できるようにすることを確実にできる。
呼び出されると、このメソッドは、ユーザーのシステム上の所与の MIDI ポートへの アクセス要求を表す Promise オブジェクトを返す。 ポートが閉じられたとき(したがって、排他的アクセス システムでは、そのポートが他のアプリケーションで利用可能になったとき)、 提供された Promise は解決される。ポートが切断されている場合、Promise は 拒否される。
提供されたすべての Promise がまだ settle していなくても、
close() を複数回呼び出すことは許可される。
close() メソッドが呼び出されたとき、ユーザーエージェントは
次の手順を実行しなければならない(MUST):
promise を新しい Promise オブジェクトとし、 resolver をそれに関連付けられた resolver とする。
promise を返し、次の手順を 非同期に実行する。
port を所与の MIDIPort
オブジェクトとする。
ポートがすでに閉じている場合(その .connection が "closed" である場合。例:ポートが
まだ暗黙的にも明示的にも開かれていない、または
close()
がすでにこの
MIDIPort で
呼び出されている場合)、下の
closed とラベル付けされた手順へジャンプする。
ポートが入力ポートである場合、次の手順へスキップする。出力ポートの .state が "connected" でない場合、またはその .connection が "pending" である場合は、 すべてのキュー済み送信データを消去し、次の手順へスキップする。 将来の timestamp を持つ、システム内のすべてのキュー済み送信データを消去し、 その後、timestamp がない、または過去もしくは現在の timestamp を持つ送信メッセージの送信を完了してから、 次の手順へ進む。
基盤システムで開かれている場合はポートへのアクセスを閉じ、 基盤システムのブロッキングリソースをすべて解放する。
MIDIPort の connection 属性を
"closed" に変更し、新しい
MIDIConnectionEvent を
MIDIAccess の
statechange ハンドラーと、
MIDIPort の
statechange ハンドラーにキューイングする。
closed:resolver の
accept(value) メソッドを、port を
値引数として呼び出す。
MIDIPort
に対応する MIDI ポートが
state 属性を変更したときは常に、ユーザーエージェントは次の手順を実行するべきである
(SHOULD):
port を MIDIPort とする。
イベントを発火する:
MIDIPort で
statechange
という名前のイベントを発火し、
MIDIAccess で
statechange を発火し、
MIDIConnectionEvent を用い、port 属性を
port に設定する。
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 が
System Exclusive
アクセスを有効にしておらず、かつそのメッセージが
System Exclusive メッセージである場合、この
処理を中止する。
port で "midimessage" という名前の
イベントを発火する。
MIDIMessageEvent を用い、timeStamp
属性を、そのメッセージがシステムによって受信された時刻に設定し、
data 属性を、単一の
MIDI
メッセージを表す MIDI データバイトの
Uint8Array に設定する。
MIDI System Real Time メッセージは、 入力ストリーム内の他のメッセージの途中で実際に発生することがあると、 特に注記される。この場合、System Real Time メッセージは 発生した時点でディスパッチされ、一方、通常のメッセージは 完了するまでバッファリングされる(その後ディスパッチされる)。
WebIDL[SecureContext, Exposed=(Window,Worker)] interface MIDIOutput : MIDIPort {
undefined send(sequence<octet> data, optional DOMHighResTimeStamp timestamp = 0);
undefined clear();
};
send
対応する MIDI ポートへ送信されるメッセージをキューに入れる。
基盤となる実装は(必要であれば)シーケンスの各
メンバーを符号なし 8 ビット整数に変換する。Uint8Array ではなく
sequence を使用することで、開発者は
Uint8Array を作成する必要なく、たとえば
output.send( new Uint8Array( [ 0x90, 0x45, 0x7f ] )
); ではなく、
output.send( [ 0x90, 0x45, 0x7f ]
); という簡便さを利用できる。
data には、1 つ以上の完全な妥当な MIDI メッセージが含まれる。 Running status は、基盤システムがサポートしない可能性があるため、 data では許可されない。
data が妥当な sequence でない、または
妥当な MIDI メッセージを含まない場合、
TypeError 例外を投げる。
data が System Exclusive メッセージであり、
かつ
MIDIAccess が
System Exclusive アクセスを有効にしていない場合、
InvalidAccessError 例外を投げる。
ポートが "disconnected" である場合、
InvalidStateError 例外を投げる。
ポートが "connected" であるが、 connection が "closed" である場合、 非同期にポートを開くことを試みる。
DOMHighResTimeStamp
として、文書の navigation start から相対的に測定された
ミリ秒数)。timestamp が 0(または過去の別の時刻)に
設定されている場合、データはできるだけ早く送信される。
同じ timestamp で send() を複数回呼び出した場合、
そのデータは呼び出しが行われた順序で送信されなければならない。
clear
MIDIOutput のキューから、
まだ送信されていないすべてのキュー済み送信データを消去する。実装は、
MIDI ストリームが良好な状態に残されることを保証する必要があるため、
出力ポートが sysex メッセージの途中にある場合、sysex
終了バイト(0xf7)が送信されるべきである。
WebIDLenum MIDIPortType {
"input",
"output",
};
input
MIDIPort が入力ポートである場合、type メンバーは
この値でなければならない(MUST)。
output
MIDIPort が出力ポートである場合、type メンバーは
この値でなければならない(MUST)。
WebIDLenum MIDIPortDeviceState {
"disconnected",
"connected",
};
disconnected
MIDIPort が表すデバイスは
システムから切断されている。デバイスがシステムから切断されている場合、それは
入力および出力ポートの関連する map に現れるべきではない。
connected
MIDIPort が表すデバイスは
接続されており、入力および出力ポートの map に現れるべきである。
WebIDLenum MIDIPortConnectionState {
"open",
"closed",
"pending",
};
open
MIDIPort が表すデバイスは
(暗黙的または明示的に)
開かれており、使用可能である。
closed
MIDIPort が表すデバイスは
開かれていない、または
明示的に閉じられている。MIDIPort が
明示的に(MIDIPort.open() を通じて)または暗黙的に
(入力ポートに midimessage
イベントハンドラーを追加すること、または出力ポートで
MIDIOutput.send()
を呼び出すことによって)開かれるまでは、これはデバイスの既定状態であるべきである。
pending
MIDIPort が表すデバイスは
(暗黙的または
明示的に)開かれていたが、その後デバイスが切断され、
使用できない状態にある。デバイスが再接続された場合、
statechange
イベントを送信する前に、システムは(
MIDIPort を開くアルゴリズムに従って)
デバイスを再び開くことを試みるべきである。これにより、connection state は
"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
単一のMIDI メッセージの MIDI データバイトを含む Uint8Array。
WebIDLdictionary MIDIMessageEventInit: EventInit {
Uint8Array data;
};
data
単一のMIDI メッセージの MIDI データバイトを含む Uint8Array。
このインターフェイスを実装するイベントオブジェクトは、
新しいポートが利用可能になったとき(たとえば、MIDI デバイスがコンピューターに初めて
接続されたとき)、以前利用可能であったポートが利用不可になったとき、
または再び利用可能になったとき(たとえば、MIDI インターフェイスが
切断され、その後再接続されたとき)、
MIDIAccess の
onstatechange
ハンドラーに渡される。
また(存在する場合)、そのポートを参照する任意の
MIDIPort の
onstatechange ハンドラーにも渡される。
MIDIPort が
"pending" 状態にあり、デバイスが
ホストシステムに再接続された場合、
statechange イベントを発火する前に、
そのポートを再び開くことを試みるため、
MIDIPort を開くアルゴリズムがその上で実行される。この
遷移が失敗した場合(例:ポートが基盤システム内の別の何かによって予約されており、
したがって使用できない場合)、connection
state は "closed" に移動し、そうでない場合は "open" に戻る。
これは、デバイス状態変更に対する
statechange
イベントの前に行われるため、そのイベントは最終的な connection state と
device state の両方を反映する。
一部の基盤システムは、デバイス接続状態の通知イベントを提供しない場合がある。 そのようなシステムでは、新しいデバイスをまれにポーリングするため、 長い時間遅延が生じることがある。そのため、 接続イベントに大きく依存しないことが推奨される。
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 でホストコンピューターに接続されるほとんどのデバイスが含まれる。 なぜなら、USB-MIDI デバイスは 通常、それ自身のMIDI インターフェイスを持ち、列挙されるためである。 5 ピン DIN ケーブルでMIDI インターフェイスに接続された個々のサンプラーまたはシンセサイザーの MIDI デバイスは列挙されない。 フィンガープリンティングされ得るインターフェイスは MIDI の「ポート」に相当し、 各 MIDI インターフェイスについて、この API はデバイス名、 製造者、およびMIDI インターフェイスの 不透明な識別子を公開する。
ほとんどのシステムにはMIDI インターフェイスが接続されていない。 多数のMIDI インターフェイスが接続されている システムは少ない。したがって、MIDI デバイスを列挙することによる追加の フィンガープリンティング露出は、Gamepad API がゲームパッドの列挙を通じて持つ 追加のフィンガープリンティング露出と類似している。典型的なユーザーでは、 接続されているデバイスは多くても数個であり、その構成は変化し得るし、 公開される情報はインターフェイス自体に関するもの(すなわち、ユーザーが設定したデータではない)である。
最初のMIDI デバイスは、Web プラットフォームとそのセキュリティリスクが 存在する前の 1983 年にリリースされた。多くのMIDI デバイスは、 製造者がサポートを停止してから長い時間が経過した後も使用されている。 MIDI は、元のシリアル接続を超えた FireWire、USB、Bluetooth などの転送方式に適応してきた。これは、 公式サポートを持たないが現在も活発に使用され、設計者が想定していなかった方法で コンピューターや Web に接続されている、異なる時代のデバイスの長い尾を伴う セキュリティ上の課題をもたらす。
懸念される理論上の攻撃の 1 つに、USB-MIDI デバイスに対する悪意のある ファームウェア更新がある。一般に USB デバイスは、 USB デバイス自身から送信されるデバイス記述子に基づいて動作できる。 USB-MIDI デバイスの ファームウェアが送信される記述子を変更できる場合、 そのデバイスは自身をヒューマンインターフェイスデバイスとして動作させることができる。 これにより、悪意のある Web サイトがホストコンピューター上の キーストロークやその他のイベントを読み取ったり注入したりできるようになり、 システム全体の侵害につながる可能性がある。
攻撃は次のように進行する:
上記の攻撃を可能にするためには、MIDI デバイスについて、 次のすべてが真である必要がある:
悪意のあるファームウェア更新に対して脆弱であるが、他の条件を満たさない MIDI デバイスは、この攻撃でホストシステムを侵害するために 使用することはできない。それでも悪意のあるファームウェア更新は、これらの MIDI デバイスを 動作不能にしたり、望ましくない方法で動作させたりする可能性がある。
このリスクを軽減するため、実装者は実装において 次の点を重視するべきである:
requestMIDIAccess() を、
権限プロンプト内のテキストなどを通じて、ファームウェア更新のリスクを
ユーザーに知らせる方法で実装する。
既知の MIDI デバイスのリストを明示的に許可またはブロックすることも、 この特定の攻撃を軽減するのに役立つ可能性がある。しかし、 多くの小企業や個人が MIDI デバイスを作っており、 多くの MIDI デバイスはもはやサポートされていないため、 これを行うと Web MIDI API の使いやすさが大幅に低下する。
利用可能なポートを識別することによるフィンガープリンティングの懸念とは別に、 MIDI メッセージの送受信に関する懸念がある。 それらの問題は以下でより詳しく検討される。
MIDI メッセージは、System Exclusive メッセージと、短い(非System Exclusive)メッセージに 分けることができる。System Exclusive メッセージはさらに、 広く認識されている MIDI Time Code や MIDI Sample Dump Standard のような Universal System Exclusive メッセージと、 他のデバイスには適用されない「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: