web_midi/
lib.rs

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 onmidimessage(&self) -> ... {
60    //     todo!()
61    // }
62
63    // pub fn set_onmidimessage(&self) -> ... {
64    //     todo!()
65    // }
66
67    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 fn state(&self) -> MidiPortDeviceState {
84    //     self.input.state()
85    // }
86
87    // pub fn connection(&self) -> MidiPortConnectionState {
88    //     self.input.connection()
89    // }
90
91    // pub fn onstatechange(&self) -> ... {
92    //     todo!()
93    // }
94
95    // pub fn set_onstatechange(&self) -> ... {
96    //     todo!()
97    // }
98
99    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    // TODO: fix input and output types to be something sensible
120    pub fn send(&self, data: &JsValue) -> Result<(), JsValue> {
121        self.output.send(data)
122    }
123
124    // TODO: fix input and output types to be something sensible
125    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 fn state(&self) -> MidiPortDeviceState {
146    //     self.output.state()
147    // }
148
149    // pub fn connection(&self) -> MidiPortConnectionState {
150    //     self.output.connection()
151    // }
152
153    // pub fn onstatechange(&self) -> ... {
154    //     todo!()
155    // }
156
157    // pub fn set_onstatechange(&self) -> ... {
158    //     todo!()
159    // }
160
161    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}