102 lines
4.4 KiB
HTML
102 lines
4.4 KiB
HTML
<!doctype html>
|
|
<html lang="vi">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>VST GUI</title>
|
|
<style>
|
|
body { font-family: system-ui, sans-serif; background: #1a1d24; color: #c8ccd4;
|
|
height: 100vh; margin: 0; display: flex; }
|
|
#editor { flex: 1; position: relative; }
|
|
#panel { width: 260px; border-left: 1px solid #2c313b; padding: 10px; overflow-y: auto;
|
|
background: #171a20; }
|
|
#panel h3 { margin: 4px 0 10px; font-size: 13px; color: #9aa3b2; font-weight: 600;
|
|
text-transform: uppercase; letter-spacing: .04em; }
|
|
.row { margin-bottom: 10px; }
|
|
.row label { display: block; font-size: 12px; color: #c8ccd4; margin-bottom: 2px;
|
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.row .val { float: right; color: #6ea8ff; font-variant-numeric: tabular-nums; }
|
|
.row input[type=range] { width: 100%; accent-color: #3b82f6; }
|
|
#msg { padding: 20px; text-align: center; color: #9aa3b2; line-height: 1.6; }
|
|
code { background: #262b34; padding: 2px 6px; border-radius: 4px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="editor"><div id="msg">Plugin editor attach vào HWND (vùng này).<br>Nếu không thấy editor: cửa sổ này mở qua DAW, native DLL phải tìm thấy (SF_NATIVE_HOST_DIR).</div></div>
|
|
<div id="panel">
|
|
<h3>Parameters</h3>
|
|
<div id="params"><div id="msg">Đang tải params…</div></div>
|
|
</div>
|
|
<script>
|
|
// T11: param sync 2 chiều — native đổi param -> event vst_param_changed -> cập nhật UI;
|
|
// JS kéo slider -> invoke set_vst_param -> setParamNormalized/setParameter.
|
|
// Guard chống loop: pendingSet chứa param_id JS vừa set; event echo của chính mình bị bỏ qua.
|
|
const T = window.__TAURI__;
|
|
if (!T) { document.getElementById('msg').textContent = 'Không có __TAURI__ (chạy ngoài Tauri).'; throw new Error('no tauri'); }
|
|
const { invoke } = T.core;
|
|
const { listen } = T.event;
|
|
|
|
const qs = new URLSearchParams(location.search);
|
|
const trackId = qs.get('track') || '';
|
|
const pluginId = qs.get('plugin') || '';
|
|
const pendingSet = new Set();
|
|
const sliders = new Map(); // param_id -> {slider, val}
|
|
|
|
function setValue(paramId, value) {
|
|
const el = sliders.get(paramId);
|
|
if (!el) return;
|
|
el.slider.value = value;
|
|
el.val.textContent = Number(value).toFixed(3);
|
|
}
|
|
|
|
async function refresh() {
|
|
const box = document.getElementById('params');
|
|
let list;
|
|
try {
|
|
list = await invoke('get_vst_params', { trackId, pluginId });
|
|
} catch (e) {
|
|
box.innerHTML = '<div id="msg">Lỗi: ' + String(e) + '</div>';
|
|
return;
|
|
}
|
|
if (!list || list.length === 0) {
|
|
box.innerHTML = '<div id="msg">Plugin không có param nào.</div>';
|
|
return;
|
|
}
|
|
box.innerHTML = '';
|
|
for (const p of list) {
|
|
const row = document.createElement('div');
|
|
row.className = 'row';
|
|
const lbl = document.createElement('label');
|
|
lbl.textContent = p.title;
|
|
const val = document.createElement('span');
|
|
val.className = 'val';
|
|
val.textContent = Number(p.value).toFixed(3);
|
|
const slider = document.createElement('input');
|
|
slider.type = 'range'; slider.min = 0; slider.max = 1; slider.step = 0.001;
|
|
slider.value = p.value;
|
|
slider.addEventListener('input', () => { val.textContent = parseFloat(slider.value).toFixed(3); });
|
|
slider.addEventListener('change', () => {
|
|
const v = parseFloat(slider.value);
|
|
pendingSet.add(p.param_id);
|
|
invoke('set_vst_param', { trackId, pluginId, paramId: p.param_id, value: v })
|
|
.catch(err => { console.error('set_vst_param', err); })
|
|
.finally(() => setTimeout(() => pendingSet.delete(p.param_id), 500));
|
|
});
|
|
row.appendChild(lbl); row.appendChild(val); row.appendChild(slider);
|
|
box.appendChild(row);
|
|
sliders.set(p.param_id, { slider, val });
|
|
}
|
|
}
|
|
|
|
// native đổi param (từ editor/automation) -> cập nhật UI
|
|
listen('vst_param_changed', (e) => {
|
|
const d = e.payload || {};
|
|
if (d.track_id !== trackId || d.plugin_id !== pluginId) return;
|
|
if (pendingSet.has(d.param_id)) { pendingSet.delete(d.param_id); return; } // echo của chính mình
|
|
setValue(d.param_id, d.value);
|
|
}).catch(err => console.error('listen vst_param_changed', err));
|
|
|
|
refresh().catch(err => console.error('refresh', err));
|
|
</script>
|
|
</body>
|
|
</html>
|