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 <noreply@anthropic.com>
This commit is contained in:
2026-09-25 10:37:09 +00:00
parent 5b1809cc2d
commit 665316d515

View File

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