mirror of https://github.com/jetkvm/kvm.git
124 lines
3.6 KiB
Go
124 lines
3.6 KiB
Go
//go:build cgo
|
|
// +build cgo
|
|
|
|
package audio
|
|
|
|
import (
|
|
_ "embed"
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
// Embedded C audio binaries (built during compilation)
|
|
//
|
|
//go:embed bin/jetkvm_audio_output
|
|
var audioOutputBinary []byte
|
|
|
|
//go:embed bin/jetkvm_audio_input
|
|
var audioInputBinary []byte
|
|
|
|
const (
|
|
audioBinDir = "/userdata/jetkvm/bin"
|
|
audioOutputBinPath = audioBinDir + "/jetkvm_audio_output"
|
|
audioInputBinPath = audioBinDir + "/jetkvm_audio_input"
|
|
binaryFileMode = 0755 // rwxr-xr-x
|
|
)
|
|
|
|
// ExtractEmbeddedBinaries extracts the embedded C audio binaries to disk
|
|
// This should be called during application startup before audio supervisors are started
|
|
func ExtractEmbeddedBinaries() error {
|
|
// Create bin directory if it doesn't exist
|
|
if err := os.MkdirAll(audioBinDir, 0755); err != nil {
|
|
return fmt.Errorf("failed to create audio bin directory: %w", err)
|
|
}
|
|
|
|
// Extract audio output binary
|
|
if err := extractBinary(audioOutputBinary, audioOutputBinPath); err != nil {
|
|
return fmt.Errorf("failed to extract audio output binary: %w", err)
|
|
}
|
|
|
|
// Extract audio input binary
|
|
if err := extractBinary(audioInputBinary, audioInputBinPath); err != nil {
|
|
return fmt.Errorf("failed to extract audio input binary: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// extractBinary writes embedded binary data to disk with executable permissions
|
|
func extractBinary(data []byte, path string) error {
|
|
// Check if binary already exists and is valid
|
|
if info, err := os.Stat(path); err == nil {
|
|
// File exists - check if size matches
|
|
if info.Size() == int64(len(data)) {
|
|
// Binary already extracted and matches embedded version
|
|
return nil
|
|
}
|
|
// Size mismatch - need to update
|
|
}
|
|
|
|
// Write to temporary file first for atomic replacement
|
|
tmpPath := path + ".tmp"
|
|
if err := os.WriteFile(tmpPath, data, binaryFileMode); err != nil {
|
|
return fmt.Errorf("failed to write binary to %s: %w", tmpPath, err)
|
|
}
|
|
|
|
// Atomically rename to final path
|
|
if err := os.Rename(tmpPath, path); err != nil {
|
|
os.Remove(tmpPath) // Clean up on error
|
|
return fmt.Errorf("failed to rename binary to %s: %w", path, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetAudioOutputBinaryPath returns the path to the audio output binary
|
|
func GetAudioOutputBinaryPath() string {
|
|
return audioOutputBinPath
|
|
}
|
|
|
|
// GetAudioInputBinaryPath returns the path to the audio input binary
|
|
func GetAudioInputBinaryPath() string {
|
|
return audioInputBinPath
|
|
}
|
|
|
|
// CleanupBinaries removes extracted audio binaries (useful for cleanup/testing)
|
|
func CleanupBinaries() error {
|
|
var errs []error
|
|
|
|
if err := os.Remove(audioOutputBinPath); err != nil && !os.IsNotExist(err) {
|
|
errs = append(errs, fmt.Errorf("failed to remove audio output binary: %w", err))
|
|
}
|
|
|
|
if err := os.Remove(audioInputBinPath); err != nil && !os.IsNotExist(err) {
|
|
errs = append(errs, fmt.Errorf("failed to remove audio input binary: %w", err))
|
|
}
|
|
|
|
// Try to remove directory (will only succeed if empty)
|
|
os.Remove(audioBinDir)
|
|
|
|
if len(errs) > 0 {
|
|
return fmt.Errorf("cleanup errors: %v", errs)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetBinaryInfo returns information about embedded binaries
|
|
func GetBinaryInfo() map[string]int {
|
|
return map[string]int{
|
|
"audio_output_size": len(audioOutputBinary),
|
|
"audio_input_size": len(audioInputBinary),
|
|
}
|
|
}
|
|
|
|
// init ensures binaries are extracted when package is imported
|
|
func init() {
|
|
// Extract binaries on package initialization
|
|
// This ensures binaries are available before supervisors start
|
|
if err := ExtractEmbeddedBinaries(); err != nil {
|
|
// Log error but don't panic - let caller handle initialization failure
|
|
fmt.Fprintf(os.Stderr, "Warning: Failed to extract embedded audio binaries: %v\n", err)
|
|
}
|
|
}
|