diff --git a/ts3-client/core/src/main/java/com/ts3client/audio/CaptureVoiceInput.java b/ts3-client/core/src/main/java/com/ts3client/audio/CaptureVoiceInput.java index eb45ec9..df08660 100644 --- a/ts3-client/core/src/main/java/com/ts3client/audio/CaptureVoiceInput.java +++ b/ts3-client/core/src/main/java/com/ts3client/audio/CaptureVoiceInput.java @@ -46,6 +46,8 @@ public final class CaptureVoiceInput implements VoiceInput { Math.max(1, HANGOVER_MS * VoiceFormat.SAMPLE_RATE / 1000 / VoiceFormat.FRAME_SIZE); private static final int PREROLL_FRAMES = Math.max(1, PREROLL_MS * VoiceFormat.SAMPLE_RATE / 1000 / VoiceFormat.FRAME_SIZE); + /** How long stop() waits for the capture loop to finish its frame. */ + private static final long STOP_TIMEOUT_MS = 500; private final ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); private final AtomicBoolean muted = new AtomicBoolean(false); @@ -281,9 +283,20 @@ public final class CaptureVoiceInput implements VoiceInput { public synchronized void stop() { running.set(false); - if (captureThread != null) { - captureThread.interrupt(); - captureThread = null; + Thread capture = captureThread; + captureThread = null; + if (line != null) { + line.close(); // wakes the capture loop's blocking read + line = null; + } + if (capture != null) { + // Let the loop finish its frame, so it cannot reopen the gate or overlap a restart. + capture.interrupt(); + try { + capture.join(STOP_TIMEOUT_MS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } } cleanup(); queue.clear();