FIX: Carla sử dụng bridge

This commit is contained in:
2026-08-10 07:57:26 +07:00
parent fbaac1f673
commit aa32272f36
17 changed files with 1372 additions and 34 deletions
+20
View File
@@ -17,6 +17,8 @@ window.API_BASE_URL = window.API_BASE_URL || window.location.origin;
async function apiRequest(endpoint, options = {}) {
const url = `${window.API_BASE_URL}${endpoint}`;
const headers = { ...getAuthHeaders(), ...options.headers };
// FormData: browser tự đặt Content-Type kèm boundary — không được ép JSON
if (options.body instanceof FormData) delete headers['Content-Type'];
const response = await fetch(url, { ...options, headers });
if (response.status === 401) {
@@ -67,6 +69,24 @@ window.API_BASE_URL = window.API_BASE_URL || window.location.origin;
getPluginDirs: () => apiRequest('/api/v1/plugins/dirs', { method: 'GET' }),
savePluginDirs: (dirs) => apiRequest('/api/v1/plugins/dirs', { method: 'POST', body: JSON.stringify(dirs) }),
scanPluginDirs: () => apiRequest('/api/v1/plugins/scan', { method: 'POST' }),
// Runtime capabilities — frontend gọi lúc boot để biết môi trường
// (desktop Windows / docker headless) và bật/tắt tính năng
getCapabilities: () => apiRequest('/api/v1/system/capabilities', { method: 'GET' }),
// Định vị Carla.exe (bản portable zip không cài đặt/PATH) — lưu config
setCarlaPath: (path) => apiRequest('/api/v1/system/carla-path', { method: 'POST', body: JSON.stringify({ carla_path: path }) }),
// Mở native GUI VSTi trong Carla (chỉ khi runtime=desktop + có Carla local)
openInCarla: (pluginName, pluginPath) => apiRequest('/api/v1/plugins/open-in-carla', { method: 'POST', body: JSON.stringify({ plugin_name: pluginName, plugin_path: pluginPath }) }),
// Quick-render preview VSTi (âm thật = âm export, cùng code path)
previewInstrument: (payload) => apiRequest('/api/v1/plugins/preview', { method: 'POST', body: JSON.stringify(payload) }),
// Thư viện preset VST3 (.vstpreset) — cầu nối Carla → pedalboard
listPresets: () => apiRequest('/api/v1/presets', { method: 'GET' }),
uploadPreset: (file, pluginHint) => {
const fd = new FormData();
fd.append('file', file);
if (pluginHint) fd.append('plugin_hint', pluginHint);
return apiRequest('/api/v1/presets/upload', { method: 'POST', body: fd });
},
deletePreset: (presetId) => apiRequest(`/api/v1/presets/${presetId}`, { method: 'DELETE' }),
// Native folder picker (Explorer qua Tauri bridge / PowerShell) —
// user yêu cầu dùng window explorer, không nhập tay
pickPluginDir: () => apiRequest('/api/v1/plugins/pick-dir', { method: 'POST' }),
+62
View File
@@ -0,0 +1,62 @@
// SonicForge Runtime service — phát hiện môi trường chạy (desktop Windows /
// docker headless) qua /api/v1/system/capabilities, bật/tắt tính năng theo đó.
// - data-runtime trên <html>: "desktop" | "headless"
// - data-carla="1": có Carla local (hiện nút "Mở trong Carla")
// - Phần tử có thuộc tính data-carla-only sẽ bị ẩn khi không có Carla local.
// - Thư viện preset (.vstpreset) cache trong SonicRuntime.presets — dùng cho
// dropdown gán preset vào track (Carla → pedalboard bridge).
window.SonicRuntime = window.SonicRuntime || { loaded: false, capabilities: null, presets: null };
(function () {
function getHeaders() {
const token = localStorage.getItem('sonic_token') || '';
return token ? { 'Authorization': 'Bearer ' + token } : {};
}
function load() {
return fetch(window.API_BASE_URL + '/api/v1/system/capabilities')
.then(function (r) { return r.json(); })
.then(function (data) {
var c = data && data.success ? data : { features: {} };
window.SonicRuntime.capabilities = c;
window.SonicRuntime.loaded = true;
var html = document.documentElement;
html.dataset.runtime = c.runtime || 'unknown';
html.dataset.platform = c.platform || '';
html.dataset.carla = (c.features && c.features.carla_local) ? '1' : '0';
if (c.features && c.features.carla_local === false) {
document.querySelectorAll('[data-carla-only]').forEach(function (el) {
el.style.display = 'none';
});
}
// Cache sẵn danh sách preset (static, ít thay đổi)
listPresets().catch(function () {});
return c;
})
.catch(function () { return null; });
}
function listPresets() {
if (window.SonicRuntime.presets) return Promise.resolve(window.SonicRuntime.presets);
return fetch(window.API_BASE_URL + '/api/v1/presets', { headers: getHeaders() })
.then(function (r) { return r.json(); })
.then(function (d) {
window.SonicRuntime.presets = (d && d.presets) || [];
return window.SonicRuntime.presets;
})
.catch(function () { return []; });
}
window.SonicRuntime.load = load;
window.SonicRuntime.listPresets = listPresets;
window.SonicRuntime.refreshPresets = function () {
window.SonicRuntime.presets = null;
return window.SonicRuntime.listPresets();
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', load);
} else {
load();
}
})();