From 665316d515c3bd1ff9d85f745030a1c0d58d0ede Mon Sep 17 00:00:00 2001 From: ericek111 Date: Fri, 25 Sep 2026 10:37:09 +0000 Subject: [PATCH] Hand the microphone between tabs in the order it was asked Each hand-over ran on a fresh thread, so two quick tab switches could start the new tab's capture before the old one stopped, or stop it after it started. They now run one after another on a single thread. Co-Authored-By: Claude Opus 5.5 --- .../main/java/com/ts3client/ui/MainFrame.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/ts3-client/swing/src/main/java/com/ts3client/ui/MainFrame.java b/ts3-client/swing/src/main/java/com/ts3client/ui/MainFrame.java index 8cfac6f..73928d1 100644 --- a/ts3-client/swing/src/main/java/com/ts3client/ui/MainFrame.java +++ b/ts3-client/swing/src/main/java/com/ts3client/ui/MainFrame.java @@ -37,6 +37,8 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -68,6 +70,15 @@ public final class MainFrame extends JFrame implements ServerTabPane.Listener { private BanReasonPresets banReasonPresets; /** The tab that owns the capture device; null when nobody is capturing. */ private ServerTab micTab; + /** + * Opens and closes capture lines, which can block briefly, off the EDT. One thread, so quick + * successive hand-overs stop and start the microphone in the order they were made. + */ + private final ExecutorService micHandover = Executors.newSingleThreadExecutor(r -> { + Thread t = new Thread(r, "mic-handover"); + t.setDaemon(true); + return t; + }); private MainMenuBar menuBar; private javax.swing.Timer statusTimer; @@ -393,11 +404,10 @@ public final class MainFrame extends JFrame implements ServerTabPane.Listener { micTab = tab; refreshTabs(); updateTray(); - // Closing and reopening the capture line can block briefly; keep it off the EDT. - new Thread(() -> { + micHandover.execute(() -> { if (previous != null) previous.session().setMicrophoneActive(false); if (tab != null) tab.session().setMicrophoneActive(true); - }, "mic-handover").start(); + }); } /** Gives the microphone to some connected tab when nobody holds it. */