fix: prevent Play() deadlock when device is not open

Play() held mu then called SwitchDevice() which also tried to acquire mu,
causing a deadlock. Replace with direct call to openDeviceLocked() which
does not lock.

Add regression test that verifies Play() returns an error (not deadlock)
when called on an uninitialized mixer.
This commit is contained in:
NeilClack
2026-07-11 10:16:15 -05:00
parent 141613f571
commit 72910e7006
2 changed files with 43 additions and 5 deletions
+6 -5
View File
@@ -112,14 +112,15 @@ func Play(path string, loopForever bool, cfg *db.AppConfig) error {
defer mu.Unlock()
// Check if mixer has been initialized and that a device is open
if !inited || !deviceOpen {
if !deviceOpen {
SwitchDevice("") // Re-switch to the default device
Play(path, loopForever, cfg) // Re-run the function
}
if !inited {
logger.Error("audio mixer not initialized")
return errors.New("audio mixer not initialized")
}
if !deviceOpen {
if err := openDeviceLocked(""); err != nil {
return fmt.Errorf("failed to open audio device: %w", err)
}
}
if path == "" {
logger.Error("empty audio path")
return errors.New("empty audio path")