-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhost.js
151 lines (124 loc) · 4.94 KB
/
host.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import AutomationTrack from "./AutomationTrack.js";
const player = document.querySelector("#player");
const mount = document.querySelector("#mount");
const main = document.querySelector("main");
const saveState = document.getElementById("save");
const restoreState = document.getElementById("restore");
const deleteState = document.getElementById("delete");
const inCache = document.getElementById("inCache");
const automationSelector = document.getElementById("param-select");
const download = document.getElementById("download");
const upload = document.getElementById("upload");
const input = document.getElementById("upload-input");
const automationAll = document.getElementById("automation-all");
inCache.setAttribute("data", localStorage.getItem("instanceState") != null);
// Safari...
const AudioContext =
window.AudioContext || // Default
window.webkitAudioContext || // Safari and old versions of Chrome
false;
const audioContext = new AudioContext({ latencyHint: "playback" });
const mediaElementSource = audioContext.createMediaElementSource(player);
// Very simple function to connect the plugin audionode to the host
const connectPlugin = (audioNode) => {
mediaElementSource.connect(audioNode);
audioNode.connect(audioContext.destination);
};
// Very simple function to append the plugin root dom node to the host
const mountPlugin = (domNode) => {
mount.innerHtml = "";
mount.appendChild(domNode);
};
(async () => {
// Init WamEnv
const { default: initializeWamHost } = await import("../plugins/utils/sdk/src/initializeWamHost.js");
const [hostGroupId] = await initializeWamHost(audioContext);
// Import WAM
const { default: WAM } = await import("./src/index.js");
// Create a new instance of the plugin
// You can can optionnally give more options such as the initial state of the plugin
const instance = await WAM.createInstance(hostGroupId, audioContext);
window.instance = instance;
// Connect the audionode to the host
connectPlugin(instance.audioNode);
// Load the GUI if need (ie. if the option noGui was set to true)
// And calls the method createElement of the Gui module
const pluginDomNode = await instance.createGui();
mountPlugin(pluginDomNode);
player.onplay = () => {
audioContext.resume(); // audio context must be resumed because browser restrictions
};
//State
saveState.addEventListener("click", async () => {
let state = await instance.audioNode.getState();
localStorage.setItem("instanceState", JSON.stringify(state));
inCache.setAttribute("data", true);
});
restoreState.addEventListener("click", async () => {
let state = localStorage.getItem("instanceState");
if (state) {
await instance.audioNode.setState(JSON.parse(state));
}
});
deleteState.addEventListener("click", async () => {
localStorage.removeItem("instanceState");
inCache.setAttribute("data", false);
});
download.addEventListener("click", async () => {
let state = await instance.audioNode.getState();
const blob = new Blob([JSON.stringify(state, undefined, 2)]);
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = "PedalBoard-State.json";
link.click();
});
upload.addEventListener("click", () => {
input.click();
});
input.addEventListener("change", (e) => {
let files = input.files;
if (files.length > 0 && files[0].type == "application/json") {
try {
var fr = new FileReader();
fr.onload = async () => {
await instance.audioNode.setState(JSON.parse(fr.result));
};
fr.readAsText(files[0]);
} catch {
console.warn("Could not import PedalBoard-State");
}
}
});
//Automation
instance.audioNode.addEventListener("wam-info", async () => {
window.pluginInfos = await instance.audioNode.getParameterInfo();
let keys = Object.keys(window.pluginInfos);
automationSelector.innerHTML = '<option value="">Add Automation...</option>';
for (let key of keys) {
let info = window.pluginInfos[key];
let option = document.createElement("option");
option.value = key;
option.innerHTML = `${key} ➤ ${info.minValue} - ${info.maxValue}`;
automationSelector.appendChild(option);
}
let useless = [];
for (let track of document.querySelectorAll("automation-track")) {
if (window.pluginInfos[track.paramId]?.nodeId != track.param.nodeId) useless.push(track);
}
useless.forEach((track) => track.remove());
});
automationSelector.addEventListener("input", (e) => {
const paramId = e.target.value;
const param = window.pluginInfos[paramId];
if (param && !param.track) {
param.track = true;
main.appendChild(new AutomationTrack(paramId, param));
}
});
automationAll.addEventListener("click", () => {
window.instance.audioNode.clearEvents();
for (let track of document.querySelectorAll("automation-track")) {
track.scheduleEvents(false);
}
});
})();