mirror of
https://github.com/got-feedBack/feedBack-desktop.git
synced 2026-08-10 18:59:55 +00:00
feat(diag): --debug ASIO routing diagnostics ([asio-diag])
Testers report song/game audio on the default WASAPI device while the guitar rides the selected ASIO output. The renderer-side reroute chain ([feedpak-route]/[renderer-bus]) has change-gated logs, but the native side of the story (what the engine actually opened, whether the backing transport/renderer bus is live) was invisible in tester logs. - audio-bridge: debug-gated 2s engine snapshot, change-gated + 30s heartbeat: device types/names, duplex, backing, renderer-bus health - debug:isEnabled IPC + preload audio.debugEnabled() so the static bundle can gate its verbose lines on --debug Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
09617aa417
commit
ee7abe3dc9
@@ -325,6 +325,56 @@ export function initAudioBridge(): void {
|
||||
|
||||
ipcMain.handle('audio:isAvailable', () => audio !== null);
|
||||
|
||||
// Renderer-side diagnostics gate: the static bundle's routing watcher /
|
||||
// renderer-bus feeder emit verbose [asio-diag] lines only when the app
|
||||
// runs with --debug / --verbose / SLOPSMITH_DEBUG (issue: ASIO output —
|
||||
// song audio heard on the default WASAPI device while guitar rides ASIO).
|
||||
ipcMain.handle('debug:isEnabled', () => isDebugEnabled());
|
||||
|
||||
// [asio-diag] main-process routing snapshot. Polls the engine every 2s in
|
||||
// debug mode and logs a one-line snapshot whenever the routing-relevant
|
||||
// state changes (plus a 30s heartbeat so a log without transitions still
|
||||
// proves the watcher was alive). Captures the native side of the story the
|
||||
// renderer diagnostics can't see: which device types/names the engine
|
||||
// actually opened, whether the backing transport is playing, and whether
|
||||
// the renderer bus is enabled and moving frames.
|
||||
if (audio && isDebugEnabled()) {
|
||||
let lastSnapshot = '';
|
||||
let lastLogged = 0;
|
||||
setInterval(() => {
|
||||
try {
|
||||
if (!audio) return;
|
||||
const running = !!audio.isAudioRunning?.();
|
||||
const dev = running ? audio.getCurrentDevice?.() : null;
|
||||
const bus = audio.getRendererBusMetrics?.() ?? null;
|
||||
const snapshot = JSON.stringify({
|
||||
running,
|
||||
inputType: dev?.inputType ?? '',
|
||||
outputType: dev?.outputType ?? '',
|
||||
input: dev?.input ?? '',
|
||||
output: dev?.output ?? '',
|
||||
duplex: dev?.duplex ?? null,
|
||||
backingPlaying: !!audio.isBackingPlaying?.(),
|
||||
streamOutputActive: !!audio.isStreamOutputActive?.(),
|
||||
busEnabled: bus?.enabled ?? null,
|
||||
// pushed/consumed prove frames are flowing; deltas matter,
|
||||
// absolute counts churn — bucket to "moving or not".
|
||||
busFlowing: !!bus && bus.pushedFrames > 0 && bus.consumedFrames > 0,
|
||||
busUnderflows: bus?.underflowCount ?? null,
|
||||
busOverflows: bus?.overflowCount ?? null,
|
||||
});
|
||||
const now = Date.now();
|
||||
if (snapshot !== lastSnapshot || now - lastLogged > 30000) {
|
||||
lastSnapshot = snapshot;
|
||||
lastLogged = now;
|
||||
console.log(`[asio-diag] engine: ${snapshot}`);
|
||||
}
|
||||
} catch (e: any) {
|
||||
console.warn(`[asio-diag] snapshot failed: ${e.message}`);
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
// ── Device Management ──────────────────────────────────────────────────
|
||||
|
||||
ipcMain.handle('audio:getDeviceTypes', () => {
|
||||
|
||||
@@ -212,6 +212,10 @@ const feedBackDesktopApi = {
|
||||
? ipcRenderer.invoke('audio:probeDeviceOptions', inputTypeOrType, inputName, outputTypeOrOutputName)
|
||||
: ipcRenderer.invoke('audio:probeDeviceOptions', inputTypeOrType, inputName, outputTypeOrOutputName, outputName),
|
||||
getCurrentDevice: () => ipcRenderer.invoke('audio:getCurrentDevice'),
|
||||
// True when the app runs with --debug / --verbose / SLOPSMITH_DEBUG.
|
||||
// The static bundle gates its verbose [asio-diag] routing lines on
|
||||
// this so normal runs don't spam the console.
|
||||
debugEnabled: (): Promise<boolean> => ipcRenderer.invoke('debug:isEnabled'),
|
||||
setDeviceType: (typeName: string) => ipcRenderer.invoke('audio:setDeviceType', typeName),
|
||||
setOutputDeviceType: (typeName: string) => ipcRenderer.invoke('audio:setOutputDeviceType', typeName),
|
||||
setDevice: ((
|
||||
|
||||
Reference in New Issue
Block a user