add a tone test mode that bypasses the soundcard

Add -tone-test to transmit a generated 440 Hz Opus tone and save
incoming audio to the file named by -tone-out.
Diagnosing an audio problem previously required a working capture and
playback device, which is exactly what is in question. This mode opens
no OpenAL device at all, so the network and codec path can be tested
on a machine with no sound hardware.

Open the capture file before starting the generator.
Starting transmission first left a tone goroutine running with nowhere
to write when the path was unusable.

Refuse file playback while in tone test mode, and ignore the
microphone volume keys.
Both operate on a stream that does not exist here.

Stop the generator and detach the file saver on disconnect.
A reconnect otherwise attached a second saver to the same file.

Add -auto-transmit to key the microphone as soon as the connection is
up.
Useful for a bot or a monitoring client that should never need a
keypress. It runs from both the connect event and the point where the
audio stream is created, because the server's welcome arrives before
the stream exists.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Brandon McGinty
2026-08-20 14:42:52 -04:00
co-authored by Claude Opus 5
parent 17a4662c6c
commit ecca0a63ed
6 changed files with 354 additions and 14 deletions
+22 -3
View File
@@ -27,9 +27,10 @@ type Barnard struct {
Address string
TLSConfig tls.Config
Stream *gumbleopenal.Stream
Tx bool
Connected bool
Stream *gumbleopenal.Stream
Tx bool
AutoTransmit bool // auto-start transmission on connect
Connected bool
Ui *uiterm.Ui
UiOutput uiterm.Textview
@@ -62,6 +63,13 @@ type Barnard struct {
FileStream *fileplayback.Player
FileStreamMutex sync.Mutex
// Added for tone test mode (bypasses all soundcard/OpenAL)
ToneTest bool
ToneTestOutput string
toneTestStop chan struct{}
toneTestSaver *AudioFileSaver
toneTestSaverDetach gumble.Detacher
// Added for recording
RecordingMutex sync.Mutex
Recorder *recording.Recorder
@@ -74,6 +82,17 @@ type Barnard struct {
adminACL *gumble.ACL
}
func (b *Barnard) cleanupToneTestAudio() {
if b.toneTestSaverDetach != nil {
b.toneTestSaverDetach.Detach()
b.toneTestSaverDetach = nil
}
if b.toneTestSaver != nil {
b.toneTestSaver.Stop()
b.toneTestSaver = nil
}
}
func (b *Barnard) StopTransmission() {
if b.Tx {
b.Notify("micdown", "me", "")