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. */