feat(debug): GUI toggle for DRED verbose logs + macOS mic permission

DRED verbose logs (off by default — keeps logcat clean in normal use):
- wzp-codec: DRED_VERBOSE_LOGS atomic flag with dred_verbose_logs() /
  set_dred_verbose_logs() helpers
- opus_enc: gate "DRED enabled" + libopus version logs behind the flag
- desktop/src-tauri/engine.rs: gate DredRecvState parse log,
  reconstruction log, classical PLC log, and DRED-counter fields in
  the Android recv heartbeat (non-verbose path still logs basic recv
  stats)
- Tauri commands set_dred_verbose_logs / get_dred_verbose_logs
- Settings panel gets a "DRED debug logs (verbose, dev only)"
  checkbox; preference persists in wzp-settings localStorage and is
  pushed to Rust on save and on app boot

macOS mic permission:
- Add desktop/src-tauri/Info.plist with NSMicrophoneUsageDescription.
  Without it, modern macOS silently denies CoreAudio capture for
  ad-hoc-signed Tauri builds — capture starts but every callback
  hands you zeros. Symptom: phones could not hear desktop client,
  desktop could still hear phones (playout has no TCC gate). The
  Tauri 2 bundler auto-merges this file into WarzonePhone.app's
  Contents/Info.plist on the next build, so first launch will pop
  the standard mic prompt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-04-11 09:48:32 +04:00
parent 16890576fb
commit 578ff8cff4
7 changed files with 143 additions and 50 deletions

View File

@@ -82,6 +82,7 @@ const settingsBtnCall = document.getElementById("settings-btn-call")!;
const sRoom = document.getElementById("s-room") as HTMLInputElement;
const sAlias = document.getElementById("s-alias") as HTMLInputElement;
const sOsAec = document.getElementById("s-os-aec") as HTMLInputElement;
const sDredDebug = document.getElementById("s-dred-debug") as HTMLInputElement;
const sAgc = document.getElementById("s-agc") as HTMLInputElement;
const sQuality = document.getElementById("s-quality") as HTMLInputElement;
const sQualityLabel = document.getElementById("s-quality-label")!;
@@ -140,6 +141,10 @@ interface Settings {
agc: boolean;
quality: string;
recentRooms: RecentRoom[];
/// When true, the Rust side emits the chatty per-frame DRED parse +
/// reconstruction + classical-PLC logs and adds DRED counters to the
/// recv heartbeat. Off in normal mode keeps logcat clean.
dredDebugLogs: boolean;
}
function loadSettings(): Settings {
@@ -152,6 +157,7 @@ function loadSettings(): Settings {
],
selectedRelay: 0, room: "general", alias: "",
osAec: true, agc: true, quality: "auto", recentRooms: [],
dredDebugLogs: false,
};
try {
const raw = localStorage.getItem("wzp-settings");
@@ -402,6 +408,10 @@ function renderRecentRooms(rooms: RecentRoom[]) {
// ── Init ──
applySettings();
setTimeout(pingAllRelays, 300);
// Hydrate the Rust DRED verbose-logs flag from saved settings on boot so
// the choice survives app restarts without needing the user to reopen
// the settings panel.
invoke("set_dred_verbose_logs", { enabled: !!loadSettings().dredDebugLogs }).catch(() => {});
// Load fingerprint + alias + git hash + render identicon
interface AppInfo { git_hash: string; alias: string; fingerprint: string; data_dir: string }
@@ -714,6 +724,7 @@ listen("call-event", (event: any) => {
function openSettings() {
const s = loadSettings();
sRoom.value = s.room; sAlias.value = s.alias; sOsAec.checked = s.osAec;
sDredDebug.checked = !!s.dredDebugLogs;
const qi = qualityToIndex(s.quality || "auto");
sQuality.value = String(qi);
updateQualityUI(qi);
@@ -753,7 +764,11 @@ settingsSave.addEventListener("click", () => {
const s = loadSettings();
s.room = sRoom.value; s.alias = sAlias.value; s.osAec = sOsAec.checked;
s.quality = QUALITY_STEPS[parseInt(sQuality.value)] || "auto";
s.dredDebugLogs = sDredDebug.checked;
saveSettingsObj(s);
// Push the new flag to the Rust side immediately so the next encoded
// frame already honors it without waiting for an app restart.
invoke("set_dred_verbose_logs", { enabled: s.dredDebugLogs }).catch(() => {});
roomInput.value = s.room; aliasInput.value = s.alias; osAecCheckbox.checked = s.osAec;
renderRecentRooms(s.recentRooms);
closeSettings();