github.com/noriah/catnip@v1.8.5/input/ffmpeg/alsa.go (about) 1 //go:build linux 2 3 package ffmpeg 4 5 import ( 6 "bufio" 7 "fmt" 8 "os" 9 "strings" 10 11 "github.com/noriah/catnip/input" 12 "github.com/pkg/errors" 13 ) 14 15 func init() { 16 input.RegisterBackend("ffmpeg-alsa", ALSA{}) 17 } 18 19 type ALSA struct{} 20 21 func (p ALSA) Init() error { 22 return nil 23 } 24 25 func (p ALSA) Close() error { 26 return nil 27 } 28 29 func (p ALSA) Devices() ([]input.Device, error) { 30 f, err := os.Open("/proc/asound/pcm") 31 if err != nil { 32 return nil, errors.Wrap(err, "failed to open pcm") 33 } 34 defer f.Close() 35 36 var devices []input.Device 37 38 scanner := bufio.NewScanner(f) 39 for scanner.Scan() { 40 prefix := strings.Split(scanner.Text(), ":")[0] 41 42 d, err := ParseALSADevice(prefix) 43 if err != nil { 44 return nil, fmt.Errorf("failed to parse device %q: %w", prefix, err) 45 } 46 47 devices = append(devices, d) 48 } 49 50 return devices, nil 51 } 52 53 func (p ALSA) DefaultDevice() (input.Device, error) { 54 return ALSADevice("default"), nil 55 } 56 57 func (p ALSA) Start(cfg input.SessionConfig) (input.Session, error) { 58 dv, ok := cfg.Device.(ALSADevice) 59 if !ok { 60 return nil, fmt.Errorf("invalid device type %T", cfg.Device) 61 } 62 63 return NewSession(dv, cfg) 64 } 65 66 // ALSADevice is a string that is the path to /dev/audioN. 67 type ALSADevice string 68 69 // ParseALSADevice parses %d:%d 70 func ParseALSADevice(hwString string) (ALSADevice, error) { 71 nparts := strings.Split(hwString, "-") 72 alsadv := "hw" 73 74 if len(nparts) == 0 || len(nparts) > 2 { 75 return "", fmt.Errorf("mismatch alsa format") 76 } 77 78 for i, part := range nparts { 79 // Trim prefixed zeros. 80 part = strings.TrimPrefix(part, "0") 81 82 switch i { 83 case 0: 84 alsadv += ":" + part 85 case 1: 86 alsadv += "," + part 87 } 88 } 89 90 return ALSADevice(alsadv), nil 91 } 92 93 func (d ALSADevice) InputArgs() []string { 94 return []string{"-f", "alsa", "-i", string(d)} 95 } 96 97 func (d ALSADevice) String() string { 98 return string(d) 99 }