fix(audio,voice,log): six P0 issues from Korean Windows test
1. Voice Bar 'Leave voice' button removed entirely. TeamSpeak users are always in some channel; Discord/Mumble-style leave is the wrong model. To stop being heard / hearing, mute mic / speaker. To physically move, tap a different channel. The voiceLeave bridge call + _onLeaveVoice stay as dead code for now (marked unused) so existing tests/integrations don't break. 2. voice_join now confirms the move actually applied server-side by polling the snapshot for up to 1.5 s and matching our own client's channel against the requested one. If the server rejected the move (no permission, wrong password, channel full), voice_join rolls the selector back to in_channel=false and returns Err so the UI surfaces the failure instead of showing a fake 'joined' state. 3. ServerSnapshot + BridgeSnapshot gain own_client_id so the UI can identify our row without name-matching. find_own_in reads it directly. 4. set_self_muted now also clamps the TransmitModeSelector's hard_mute when input is muted server-side. Without this, the Opus encoder kept producing frames after setInputMuted(true), tsclientlib refused each one with 'Sending audio while muted', and the log grew to 200 MB on the Korean host. 5. tsclientlib WARN spam suppressed via tracing filter (tsclientlib=error). Belt-and-braces on top of fix 4. 6. Log file is now rotated at every launch (not just when >4 MiB). Two generations kept: chanora.log.1 (previous) and chanora.log.2 (the one before). The bug that produced 200 MB files was a chatty subsystem flooding a single session; the per-launch rotate keeps disk use bounded by what one session can produce in its lifetime. Bonus Windows fix (separate from the six but found in the same log): the Raw Input + Hook backends now signal readiness BEFORE blocking on GetMessageW. Previously init_tx.send was called after the loop returned (i.e. on WM_QUIT, which never happens during arming), so the main thread's 2 s readiness probe always timed out and the backend reported L0Focused even when registration succeeded. Both run_raw_input_loop and run_hook_loop now take an init_tx parameter and call report!(true) right after a successful registration, and report!(false) on every early-fail return. cargo check --workspace: clean. cargo test --workspace --lib: 80 passed / 0 failed / 1 ignored. flutter analyze: clean (6 pre-existing Radio.groupValue infos).
This commit is contained in:
@@ -262,9 +262,14 @@ impl DesktopPttBackend for WindowsRawInputBackend {
|
||||
});
|
||||
});
|
||||
|
||||
let ok = unsafe { run_raw_input_loop() };
|
||||
// Run the loop. Pass `init_tx` so the loop can
|
||||
// signal readiness AFTER RegisterRawInputDevices
|
||||
// succeeds but BEFORE GetMessageW starts blocking
|
||||
// — otherwise the main thread's readiness probe
|
||||
// times out (the signal would only fire when
|
||||
// WM_QUIT was eventually delivered).
|
||||
let ok = unsafe { run_raw_input_loop(init_tx) };
|
||||
armed.store(ok, Ordering::Release);
|
||||
let _ = init_tx.send(ok);
|
||||
|
||||
// If init failed, exit immediately. If it
|
||||
// succeeded, run_raw_input_loop already ran the
|
||||
@@ -365,7 +370,20 @@ impl Drop for WindowsRawInputBackend {
|
||||
/// # Safety
|
||||
/// Calls into Win32 directly. Must be invoked on the thread that
|
||||
/// owns the message window (created here).
|
||||
unsafe fn run_raw_input_loop() -> bool {
|
||||
unsafe fn run_raw_input_loop(init_tx: std::sync::mpsc::Sender<bool>) -> bool {
|
||||
// Helper that signals the readiness state to the main thread.
|
||||
// We send exactly once at the first decisive moment (either an
|
||||
// early-fail return or right after a successful
|
||||
// RegisterRawInputDevices). Subsequent sends are no-ops.
|
||||
let mut signal = Some(init_tx);
|
||||
macro_rules! report {
|
||||
($v:expr) => {
|
||||
if let Some(tx) = signal.take() {
|
||||
let _ = tx.send($v);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Create a hidden message-only window. We need it as the
|
||||
// hwndTarget on the RAWINPUTDEVICE so RIDEV_INPUTSINK delivery
|
||||
// works even when our process has no visible window focus.
|
||||
@@ -377,6 +395,7 @@ unsafe fn run_raw_input_loop() -> bool {
|
||||
error = %e,
|
||||
"windows ptt: GetModuleHandleW failed"
|
||||
);
|
||||
report!(false);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -415,6 +434,7 @@ unsafe fn run_raw_input_loop() -> bool {
|
||||
target: "chanora_audio",
|
||||
"windows ptt: CreateWindowExW(HWND_MESSAGE) returned null"
|
||||
);
|
||||
report!(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -445,6 +465,7 @@ unsafe fn run_raw_input_loop() -> bool {
|
||||
target: "chanora_audio",
|
||||
"windows ptt: RegisterRawInputDevices failed"
|
||||
);
|
||||
report!(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -452,6 +473,11 @@ unsafe fn run_raw_input_loop() -> bool {
|
||||
target: "chanora_audio",
|
||||
"windows ptt: Raw Input devices registered (keyboard + mouse, INPUTSINK)"
|
||||
);
|
||||
// Signal readiness NOW (before we block on GetMessageW). The
|
||||
// main thread's init probe is waiting for this; the loop runs
|
||||
// until WM_QUIT and the return value at end-of-life is no
|
||||
// longer used as a readiness signal.
|
||||
report!(true);
|
||||
|
||||
// Message pump. GetMessageW returns 0 on WM_QUIT, -1 on error.
|
||||
let mut msg = MSG::default();
|
||||
@@ -695,9 +721,8 @@ impl DesktopPttBackend for WindowsHookBackend {
|
||||
});
|
||||
});
|
||||
|
||||
let ok = unsafe { run_hook_loop() };
|
||||
let ok = unsafe { run_hook_loop(init_tx) };
|
||||
armed.store(ok, Ordering::Release);
|
||||
let _ = init_tx.send(ok);
|
||||
|
||||
HOOK_CTX.with(|cell| {
|
||||
*cell.borrow_mut() = None;
|
||||
@@ -770,7 +795,16 @@ impl Drop for WindowsHookBackend {
|
||||
/// # Safety
|
||||
/// Calls Win32 directly; must run on the thread that owns the
|
||||
/// hook handles.
|
||||
unsafe fn run_hook_loop() -> bool {
|
||||
unsafe fn run_hook_loop(init_tx: std::sync::mpsc::Sender<bool>) -> bool {
|
||||
let mut signal = Some(init_tx);
|
||||
macro_rules! report {
|
||||
($v:expr) => {
|
||||
if let Some(tx) = signal.take() {
|
||||
let _ = tx.send($v);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let h_instance: HMODULE = match GetModuleHandleW(None) {
|
||||
Ok(h) => h,
|
||||
Err(e) => {
|
||||
@@ -779,6 +813,7 @@ unsafe fn run_hook_loop() -> bool {
|
||||
error = %e,
|
||||
"windows ptt: GetModuleHandleW failed (hook)"
|
||||
);
|
||||
report!(false);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -794,6 +829,7 @@ unsafe fn run_hook_loop() -> bool {
|
||||
error = %e,
|
||||
"windows ptt: SetWindowsHookExW(WH_KEYBOARD_LL) failed"
|
||||
);
|
||||
report!(false);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -806,6 +842,7 @@ unsafe fn run_hook_loop() -> bool {
|
||||
"windows ptt: SetWindowsHookExW(WH_MOUSE_LL) failed"
|
||||
);
|
||||
let _ = UnhookWindowsHookEx(kbd_hook);
|
||||
report!(false);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -814,6 +851,10 @@ unsafe fn run_hook_loop() -> bool {
|
||||
target: "chanora_audio",
|
||||
"windows ptt: low-level hooks installed (WH_KEYBOARD_LL + WH_MOUSE_LL)"
|
||||
);
|
||||
// Signal readiness now, before blocking on GetMessageW. The
|
||||
// return value at end-of-loop is no longer used by the init
|
||||
// probe.
|
||||
report!(true);
|
||||
|
||||
let mut msg = MSG::default();
|
||||
loop {
|
||||
|
||||
Reference in New Issue
Block a user