Skip to content

Commit 4edc86f

Browse files
cleanup hacky fixes + minify polyfill + better docs
1 parent f97a683 commit 4edc86f

File tree

4 files changed

+48
-279
lines changed

4 files changed

+48
-279
lines changed

guest-js/index.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class TauriMIDIAccess extends EventTarget implements MIDIAccess {
88

99
inputs = new Map<string, TauriMIDIInput>();
1010
outputs = new Map<string, TauriMIDIOutput>();
11+
ready: Promise<void>;
1112

1213
onstatechange: ((this: MIDIAccess, ev: Event) => any) | null = null;
1314

@@ -30,6 +31,13 @@ class TauriMIDIAccess extends EventTarget implements MIDIAccess {
3031
constructor() {
3132
super();
3233

34+
// TODO: This could be `Promise.withResolvers` when it's stable
35+
let resolve: (value: any) => void;
36+
this.ready = new Promise((r, reject) => {
37+
resolve = r;
38+
setTimeout(() => reject(new Error("Failed to initialise WebMIDI")), 10_000);
39+
});
40+
3341
events.stateChange.listen((event: any) => {
3442
const { inputs, outputs } = event.payload;
3543

@@ -76,6 +84,7 @@ class TauriMIDIAccess extends EventTarget implements MIDIAccess {
7684
}
7785

7886
if (dirty) this.dispatchEvent(new Event("statechange"));
87+
resolve(void 0);
7988
});
8089
}
8190
}
@@ -150,6 +159,9 @@ class TauriMIDIMessageEvent extends Event implements MIDIMessageEvent {
150159
class TauriMIDIInput extends TauriMIDIPort implements MIDIInput {
151160
constructor(name: string) {
152161
super(name, "input");
162+
this.addEventListener("midimessage", (cb) => {
163+
if (this.onmidimessage) this.onmidimessage(cb);
164+
});
153165
}
154166

155167
private stopListening?: Promise<UnlistenFn>;
@@ -177,18 +189,14 @@ class TauriMIDIInput extends TauriMIDIPort implements MIDIInput {
177189
return super.close();
178190
}
179191

180-
// TODO: Cleanup this stuff
181-
// private _onmidimessage: ((this: MIDIInput, ev: Event) => any) | null = null;
192+
private _onmidimessage: ((this: MIDIInput, ev: Event) => any) | null = null;
182193

183-
// get onmidimessage() {
184-
// return this._onmidimessage;
185-
// }
194+
get onmidimessage() {
195+
return this._onmidimessage;
196+
}
186197

187198
set onmidimessage(cb: ((this: MIDIInput, ev: Event) => any) | null) {
188-
// this._onmidimessage = cb;
189-
190-
this.addEventListener("midimessage", cb as any);
191-
199+
this._onmidimessage = cb;
192200
if (this.connection !== "open") this.open();
193201
}
194202
}
@@ -213,12 +221,4 @@ class TauriMIDIOutput extends TauriMIDIPort implements MIDIOutput {
213221

214222
const access = new TauriMIDIAccess();
215223

216-
// TODO: We could possible just ensure `access` already has data so this can be done while JS is still loading in the webview
217-
// TODO: and then it only every await's the first time.
218-
navigator.requestMIDIAccess = () => {
219-
// We wait for the next update to ensure we have initialised the inputs and outputs.
220-
// This event is emitted regularly by the backend
221-
return new Promise((resolve) => access.addEventListener("statechange", () => resolve(access)));
222-
};
223-
224-
// navigator.requestMIDIAccess = () => Promise.resolve(access);
224+
navigator.requestMIDIAccess = () => access.ready.then(() => access);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"type": "module",
44
"private": true,
55
"scripts": {
6-
"build": "tsc --noEmit && esbuild ./guest-js/index.ts --bundle --outfile=src/polyfill.js --platform=browser"
6+
"build": "tsc --noEmit && esbuild ./guest-js/index.ts --bundle --minify --outfile=src/polyfill.js --platform=browser"
77
},
88
"devDependencies": {
99
"@tauri-apps/api": "2.0.0-rc.6",

src/lib.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
//! A WebMIDI-compatible plugin for Tauri
2+
//!
3+
//! Refer to the [init](fn.init.html) function for more information on how to use this plugin or checkout [the example](https://github.com/specta-rs/tauri-plugin-midi/tree/main/example).
24
35
use std::{
46
collections::BTreeMap,
@@ -182,16 +184,38 @@ fn builder<R: Runtime>() -> tauri_specta::Builder<R> {
182184
.events(tauri_specta::collect_events![StateChange, MIDIMessage])
183185
}
184186

185-
/// Initialise the Tauri MIDI plugin
187+
/// Initialise the plugin which will take care of polyfilling WebMIDI into any Tauri webviews.
186188
///
187-
/// # Example
189+
/// # Usage
190+
///
191+
/// Using this plugin is very simple. Just add it to your Tauri builder:
188192
///
189193
/// ```rust
190194
/// tauri::Builder::default()
191-
/// // Just add this plugin to your Tauri builder
192-
/// .plugin(tauri_plugin_midi::init());
195+
/// .plugin(tauri_plugin_midi::init()) // <- This bit here
196+
/// # ;
193197
/// // .... rest of your builder
194198
/// ```
199+
///
200+
/// Then give permissions to the plugin by adding the `midi:default` permissions to your application.
201+
///
202+
/// This can be done by modifying the `capabilities/default.json` file:
203+
/// ```json
204+
/// {
205+
/// "$schema": "../gen/schemas/desktop-schema.json",
206+
/// "identifier": "default",
207+
/// "description": "Capability for the main window",
208+
/// "windows": ["main"],
209+
/// "permissions": ["core:default", "midi:default"] // <- add `midi:default` into here
210+
/// }
211+
/// ```
212+
///
213+
/// and now you can use the regular [WebMIDI API](https://developer.mozilla.org/en-US/docs/Web/API/Web_MIDI_API) from within your webview.
214+
///
215+
/// ## Known issues
216+
///
217+
/// - This plugin doesn't work within iframes at the moment. It's being tracked as [#7](https://github.com/specta-rs/tauri-plugin-midi/issues/7)
218+
///
195219
pub fn init<R: Runtime>() -> TauriPlugin<R> {
196220
let builder = builder::<R>();
197221

src/polyfill.js

Lines changed: 1 addition & 256 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)