kvm/internal/audio/api.go

105 lines
3.0 KiB
Go

package audio
import (
"os"
"strings"
"sync/atomic"
"unsafe"
)
var (
globalOutputSupervisor unsafe.Pointer // *AudioOutputSupervisor
globalInputSupervisor unsafe.Pointer // *AudioInputSupervisor
)
// isAudioServerProcess detects if we're running as the audio server subprocess
func isAudioServerProcess() bool {
for _, arg := range os.Args {
if strings.Contains(arg, "--audio-output-server") {
return true
}
}
return false
}
// StartAudioStreaming launches the audio stream.
// In audio server subprocess: uses CGO-based audio streaming
// In main process: this should not be called (use StartAudioRelay instead)
func StartAudioStreaming(send func([]byte)) error {
if isAudioServerProcess() {
// Audio server subprocess: use CGO audio processing
return StartAudioOutputStreaming(send)
} else {
// Main process: should use relay system instead
// This is kept for backward compatibility but not recommended
return StartAudioOutputStreaming(send)
}
}
// StopAudioStreaming stops the audio stream.
func StopAudioStreaming() {
if isAudioServerProcess() {
// Audio server subprocess: stop CGO audio processing
StopAudioOutputStreaming()
} else {
// Main process: stop relay if running
StopAudioRelay()
}
}
// StartNonBlockingAudioStreaming is an alias for backward compatibility
func StartNonBlockingAudioStreaming(send func([]byte)) error {
return StartAudioOutputStreaming(send)
}
// StopNonBlockingAudioStreaming is an alias for backward compatibility
func StopNonBlockingAudioStreaming() {
StopAudioOutputStreaming()
}
// SetAudioOutputSupervisor sets the global audio output supervisor
func SetAudioOutputSupervisor(supervisor *AudioOutputSupervisor) {
atomic.StorePointer(&globalOutputSupervisor, unsafe.Pointer(supervisor))
}
// GetAudioOutputSupervisor returns the global audio output supervisor
func GetAudioOutputSupervisor() *AudioOutputSupervisor {
ptr := atomic.LoadPointer(&globalOutputSupervisor)
if ptr == nil {
return nil
}
return (*AudioOutputSupervisor)(ptr)
}
// SetAudioInputSupervisor sets the global audio input supervisor
func SetAudioInputSupervisor(supervisor *AudioInputSupervisor) {
atomic.StorePointer(&globalInputSupervisor, unsafe.Pointer(supervisor))
}
// GetAudioInputSupervisor returns the global audio input supervisor
func GetAudioInputSupervisor() *AudioInputSupervisor {
ptr := atomic.LoadPointer(&globalInputSupervisor)
if ptr == nil {
return nil
}
return (*AudioInputSupervisor)(ptr)
}
// PrewarmAudioInputSubprocess starts an audio input subprocess in advance to reduce activation latency
func PrewarmAudioInputSubprocess() error {
supervisor := GetAudioInputSupervisor()
if supervisor == nil {
return nil // No supervisor available, skip prewarming
}
return supervisor.PrewarmSubprocess()
}
// IsAudioInputSubprocessPrewarmed returns whether an audio input subprocess is prewarmed and ready
func IsAudioInputSubprocessPrewarmed() bool {
supervisor := GetAudioInputSupervisor()
if supervisor == nil {
return false
}
return supervisor.IsPrewarmed()
}