1use js_sys::Array;
2use wasm_bindgen::JsValue;
3use wasm_bindgen_futures::JsFuture;
4use web_sys::MidiOptions;
5
6pub struct MidiAccess {
7 access: web_sys::MidiAccess,
8}
9
10impl MidiAccess {
11 pub async fn get_access() -> Self {
12 let window = web_sys::window().expect("no global `window` exists");
13
14 let access: web_sys::MidiAccess = JsFuture::from(
15 window
16 .navigator()
17 .request_midi_access_with_options(MidiOptions::new().sysex(true).software(true))
18 .unwrap(),
19 )
20 .await
21 .unwrap()
22 .into();
23
24 Self { access }
25 }
26
27 pub fn inputs(&self) -> Vec<MidiInput> {
28 let mut result: Vec<MidiInput> = Vec::new();
29
30 for entry in js_sys::try_iter(&self.access.inputs()).unwrap().unwrap() {
31 let array: Array = entry.unwrap().into();
32 result.push(MidiInput {
33 input: array.get(1).into(),
34 });
35 }
36
37 result
38 }
39
40 pub fn outputs(&self) -> Vec<MidiOutput> {
41 let mut result: Vec<MidiOutput> = Vec::new();
42
43 for entry in js_sys::try_iter(&self.access.inputs()).unwrap().unwrap() {
44 let array: Array = entry.unwrap().into();
45 result.push(MidiOutput {
46 output: array.get(1).into(),
47 });
48 }
49
50 result
51 }
52}
53
54pub struct MidiInput {
55 input: web_sys::MidiInput,
56}
57
58impl MidiInput {
59 pub fn id(&self) -> String {
68 self.input.id()
69 }
70
71 pub fn manufacturer(&self) -> Option<String> {
72 self.input.manufacturer()
73 }
74
75 pub fn name(&self) -> Option<String> {
76 self.input.name()
77 }
78
79 pub fn version(&self) -> Option<String> {
80 self.input.version()
81 }
82
83 pub async fn open(&self) -> &Self {
100 JsFuture::from(self.input.open()).await.unwrap();
101 self
102 }
103
104 pub async fn close(&self) -> &Self {
105 JsFuture::from(self.input.close()).await.unwrap();
106 self
107 }
108}
109
110pub struct MidiOutput {
111 output: web_sys::MidiOutput,
112}
113
114impl MidiOutput {
115 pub fn clear(&self) {
116 self.output.clear()
117 }
118
119 pub fn send(&self, data: &JsValue) -> Result<(), JsValue> {
121 self.output.send(data)
122 }
123
124 pub fn send_with_timestamp(&self, data: &JsValue, timestamp: f64) -> Result<(), JsValue> {
126 self.output.send_with_timestamp(data, timestamp)
127 }
128
129 pub fn id(&self) -> String {
130 self.output.id()
131 }
132
133 pub fn manufacturer(&self) -> Option<String> {
134 self.output.manufacturer()
135 }
136
137 pub fn name(&self) -> Option<String> {
138 self.output.name()
139 }
140
141 pub fn version(&self) -> Option<String> {
142 self.output.version()
143 }
144
145 pub async fn open(&self) -> &Self {
162 JsFuture::from(self.output.open()).await.unwrap();
163 self
164 }
165
166 pub async fn close(&self) -> &Self {
167 JsFuture::from(self.output.close()).await.unwrap();
168 self
169 }
170}