Improvement: automatically resume audio when the audio usb gadget is re-enabled from settings

This commit is contained in:
Alex P 2025-08-25 12:36:04 +00:00
parent f24443e072
commit 1a0377bbdf
3 changed files with 46 additions and 16 deletions

View File

@ -170,7 +170,7 @@ func (r *AudioRelay) relayLoop() {
func (r *AudioRelay) forwardToWebRTC(frame []byte) error { func (r *AudioRelay) forwardToWebRTC(frame []byte) error {
r.mutex.RLock() r.mutex.RLock()
defer r.mutex.RUnlock() defer r.mutex.RUnlock()
audioTrack := r.audioTrack audioTrack := r.audioTrack
config := r.config config := r.config
muted := r.muted muted := r.muted

View File

@ -116,7 +116,7 @@ func (c *ChangeSetResolver) resolveChanges(initial bool) error {
} }
func (c *ChangeSetResolver) applyChanges() error { func (c *ChangeSetResolver) applyChanges() error {
return c.applyChangesWithTimeout(30 * time.Second) return c.applyChangesWithTimeout(45 * time.Second)
} }
func (c *ChangeSetResolver) applyChangesWithTimeout(timeout time.Duration) error { func (c *ChangeSetResolver) applyChangesWithTimeout(timeout time.Duration) error {

View File

@ -1,10 +1,12 @@
package usbgadget package usbgadget
import ( import (
"context"
"fmt" "fmt"
"path" "path"
"path/filepath" "path/filepath"
"sort" "sort"
"time"
"github.com/rs/zerolog" "github.com/rs/zerolog"
) )
@ -52,22 +54,50 @@ func (u *UsbGadget) newUsbGadgetTransaction(lock bool) error {
} }
func (u *UsbGadget) WithTransaction(fn func() error) error { func (u *UsbGadget) WithTransaction(fn func() error) error {
u.txLock.Lock() return u.WithTransactionTimeout(fn, 60*time.Second)
defer u.txLock.Unlock() }
err := u.newUsbGadgetTransaction(false) // WithTransactionTimeout executes a USB gadget transaction with a specified timeout
if err != nil { // to prevent indefinite blocking during USB reconfiguration operations
u.log.Error().Err(err).Msg("failed to create transaction") func (u *UsbGadget) WithTransactionTimeout(fn func() error, timeout time.Duration) error {
return err // Create a context with timeout for the entire transaction
} ctx, cancel := context.WithTimeout(context.Background(), timeout)
if err := fn(); err != nil { defer cancel()
u.log.Error().Err(err).Msg("transaction failed")
return err
}
result := u.tx.Commit()
u.tx = nil
return result // Channel to signal when the transaction is complete
done := make(chan error, 1)
// Execute the transaction in a goroutine
go func() {
u.txLock.Lock()
defer u.txLock.Unlock()
err := u.newUsbGadgetTransaction(false)
if err != nil {
u.log.Error().Err(err).Msg("failed to create transaction")
done <- err
return
}
if err := fn(); err != nil {
u.log.Error().Err(err).Msg("transaction failed")
done <- err
return
}
result := u.tx.Commit()
u.tx = nil
done <- result
}()
// Wait for either completion or timeout
select {
case err := <-done:
return err
case <-ctx.Done():
u.log.Error().Dur("timeout", timeout).Msg("USB gadget transaction timed out")
return fmt.Errorf("USB gadget transaction timed out after %v: %w", timeout, ctx.Err())
}
} }
func (tx *UsbGadgetTransaction) addFileChange(component string, change RequestedFileChange) string { func (tx *UsbGadgetTransaction) addFileChange(component string, change RequestedFileChange) string {