mirror of https://github.com/jetkvm/kvm.git
Compare commits
No commits in common. "eeacceb6676460308186f2b7092a4985758e5d01" and "cd7a098f760a0b2e68a834bd91638617ab98f0c4" have entirely different histories.
eeacceb667
...
cd7a098f76
14
audio.go
14
audio.go
|
|
@ -22,7 +22,7 @@ var (
|
||||||
audioLogger zerolog.Logger
|
audioLogger zerolog.Logger
|
||||||
currentAudioTrack *webrtc.TrackLocalStaticSample
|
currentAudioTrack *webrtc.TrackLocalStaticSample
|
||||||
inputTrackHandling atomic.Bool
|
inputTrackHandling atomic.Bool
|
||||||
useUSBForAudioOutput atomic.Bool
|
useUSBForAudioOutput bool
|
||||||
audioOutputEnabled atomic.Bool
|
audioOutputEnabled atomic.Bool
|
||||||
audioInputEnabled atomic.Bool
|
audioInputEnabled atomic.Bool
|
||||||
)
|
)
|
||||||
|
|
@ -32,7 +32,7 @@ func initAudio() {
|
||||||
|
|
||||||
// Load audio output source from config
|
// Load audio output source from config
|
||||||
ensureConfigLoaded()
|
ensureConfigLoaded()
|
||||||
useUSBForAudioOutput.Store(config.AudioOutputSource == "usb")
|
useUSBForAudioOutput = config.AudioOutputSource == "usb"
|
||||||
|
|
||||||
// Enable both by default
|
// Enable both by default
|
||||||
audioOutputEnabled.Store(true)
|
audioOutputEnabled.Store(true)
|
||||||
|
|
@ -57,7 +57,7 @@ func startAudio() error {
|
||||||
// Start output audio if not running and enabled
|
// Start output audio if not running and enabled
|
||||||
if outputSource == nil && audioOutputEnabled.Load() {
|
if outputSource == nil && audioOutputEnabled.Load() {
|
||||||
alsaDevice := "hw:0,0" // HDMI
|
alsaDevice := "hw:0,0" // HDMI
|
||||||
if useUSBForAudioOutput.Load() {
|
if useUSBForAudioOutput {
|
||||||
alsaDevice = "hw:1,0" // USB
|
alsaDevice = "hw:1,0" // USB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,17 +167,16 @@ func SetAudioOutputSource(useUSB bool) error {
|
||||||
audioMutex.Lock()
|
audioMutex.Lock()
|
||||||
defer audioMutex.Unlock()
|
defer audioMutex.Unlock()
|
||||||
|
|
||||||
if useUSBForAudioOutput.Load() == useUSB {
|
if useUSBForAudioOutput == useUSB {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
audioLogger.Info().
|
audioLogger.Info().
|
||||||
Bool("old_usb", useUSBForAudioOutput.Load()).
|
Bool("old_usb", useUSBForAudioOutput).
|
||||||
Bool("new_usb", useUSB).
|
Bool("new_usb", useUSB).
|
||||||
Msg("Switching audio output source")
|
Msg("Switching audio output source")
|
||||||
|
|
||||||
oldValue := useUSBForAudioOutput.Load()
|
useUSBForAudioOutput = useUSB
|
||||||
useUSBForAudioOutput.Store(useUSB)
|
|
||||||
|
|
||||||
ensureConfigLoaded()
|
ensureConfigLoaded()
|
||||||
if useUSB {
|
if useUSB {
|
||||||
|
|
@ -187,7 +186,6 @@ func SetAudioOutputSource(useUSB bool) error {
|
||||||
}
|
}
|
||||||
if err := SaveConfig(); err != nil {
|
if err := SaveConfig(); err != nil {
|
||||||
audioLogger.Error().Err(err).Msg("Failed to save config")
|
audioLogger.Error().Err(err).Msg("Failed to save config")
|
||||||
useUSBForAudioOutput.Store(oldValue)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,7 @@ type OutputRelay struct {
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
logger zerolog.Logger
|
logger zerolog.Logger
|
||||||
running atomic.Bool
|
running atomic.Bool
|
||||||
sample media.Sample
|
sample media.Sample // Reusable sample for zero-allocation hot path
|
||||||
stopped chan struct{}
|
|
||||||
|
|
||||||
// Stats (Uint32: overflows after 2.7 years @ 50fps, faster atomics on 32-bit ARM)
|
// Stats (Uint32: overflows after 2.7 years @ 50fps, faster atomics on 32-bit ARM)
|
||||||
framesRelayed atomic.Uint32
|
framesRelayed atomic.Uint32
|
||||||
|
|
@ -39,9 +38,8 @@ func NewOutputRelay(source AudioSource, audioTrack *webrtc.TrackLocalStaticSampl
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
stopped: make(chan struct{}),
|
|
||||||
sample: media.Sample{
|
sample: media.Sample{
|
||||||
Duration: 20 * time.Millisecond,
|
Duration: 20 * time.Millisecond, // Constant for all Opus frames
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -57,15 +55,13 @@ func (r *OutputRelay) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops the relay and waits for goroutine to exit
|
// Stop stops the relay
|
||||||
func (r *OutputRelay) Stop() {
|
func (r *OutputRelay) Stop() {
|
||||||
if !r.running.Swap(false) {
|
if !r.running.Swap(false) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
r.cancel()
|
r.cancel()
|
||||||
<-r.stopped
|
|
||||||
|
|
||||||
r.logger.Debug().
|
r.logger.Debug().
|
||||||
Uint32("frames_relayed", r.framesRelayed.Load()).
|
Uint32("frames_relayed", r.framesRelayed.Load()).
|
||||||
Uint32("frames_dropped", r.framesDropped.Load()).
|
Uint32("frames_dropped", r.framesDropped.Load()).
|
||||||
|
|
@ -74,8 +70,6 @@ func (r *OutputRelay) Stop() {
|
||||||
|
|
||||||
// relayLoop continuously reads from audio source and writes to WebRTC
|
// relayLoop continuously reads from audio source and writes to WebRTC
|
||||||
func (r *OutputRelay) relayLoop() {
|
func (r *OutputRelay) relayLoop() {
|
||||||
defer close(r.stopped)
|
|
||||||
|
|
||||||
const reconnectDelay = 1 * time.Second
|
const reconnectDelay = 1 * time.Second
|
||||||
|
|
||||||
for r.running.Load() {
|
for r.running.Load() {
|
||||||
|
|
|
||||||
10
jsonrpc.go
10
jsonrpc.go
|
|
@ -899,7 +899,7 @@ func updateUsbRelatedConfig(wasAudioEnabled bool) error {
|
||||||
if config.UsbDevices != nil && !config.UsbDevices.Audio && config.AudioOutputSource == "usb" {
|
if config.UsbDevices != nil && !config.UsbDevices.Audio && config.AudioOutputSource == "usb" {
|
||||||
audioMutex.Lock()
|
audioMutex.Lock()
|
||||||
config.AudioOutputSource = "hdmi"
|
config.AudioOutputSource = "hdmi"
|
||||||
useUSBForAudioOutput.Store(false)
|
useUSBForAudioOutput = false
|
||||||
audioSourceChanged = true
|
audioSourceChanged = true
|
||||||
audioMutex.Unlock()
|
audioMutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
@ -908,7 +908,7 @@ func updateUsbRelatedConfig(wasAudioEnabled bool) error {
|
||||||
if config.UsbDevices != nil && config.UsbDevices.Audio && !wasAudioEnabled {
|
if config.UsbDevices != nil && config.UsbDevices.Audio && !wasAudioEnabled {
|
||||||
audioMutex.Lock()
|
audioMutex.Lock()
|
||||||
config.AudioOutputSource = "usb"
|
config.AudioOutputSource = "usb"
|
||||||
useUSBForAudioOutput.Store(true)
|
useUSBForAudioOutput = true
|
||||||
audioSourceChanged = true
|
audioSourceChanged = true
|
||||||
audioMutex.Unlock()
|
audioMutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
@ -970,10 +970,8 @@ func rpcSetUsbDeviceState(device string, enabled bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func rpcGetAudioOutputSource() (string, error) {
|
func rpcGetAudioOutputSource() (string, error) {
|
||||||
if useUSBForAudioOutput.Load() {
|
ensureConfigLoaded()
|
||||||
return "usb", nil
|
return config.AudioOutputSource, nil
|
||||||
}
|
|
||||||
return "hdmi", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func rpcSetAudioOutputSource(source string) error {
|
func rpcSetAudioOutputSource(source string) error {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue