github.com/noriah/catnip@v1.8.5/input/parec/parec.go (about) 1 package parec 2 3 import ( 4 "fmt" 5 6 "github.com/noisetorch/pulseaudio" 7 "github.com/noriah/catnip/input" 8 "github.com/noriah/catnip/input/common/execread" 9 "github.com/pkg/errors" 10 ) 11 12 func init() { 13 input.RegisterBackend("parec", Backend{}) 14 } 15 16 type Backend struct{} 17 18 func (p Backend) Init() error { 19 return nil 20 } 21 22 func (p Backend) Close() error { 23 return nil 24 } 25 26 func (p Backend) Devices() ([]input.Device, error) { 27 c, err := pulseaudio.NewClient() 28 if err != nil { 29 return nil, errors.Wrap(err, "failed to create client") 30 } 31 defer c.Close() 32 33 s, err := c.Sources() 34 if err != nil { 35 return nil, errors.Wrap(err, "failed to get sources") 36 } 37 38 devices := make([]input.Device, len(s)) 39 for i, source := range s { 40 devices[i] = PulseDevice(source.Name) 41 } 42 43 return devices, nil 44 } 45 46 func (p Backend) DefaultDevice() (input.Device, error) { 47 return PulseDevice(""), nil 48 } 49 50 func (p Backend) Start(cfg input.SessionConfig) (input.Session, error) { 51 return NewSession(cfg) 52 } 53 54 type PulseDevice string 55 56 // InputArgs is used for FFmpeg only. 57 func (d PulseDevice) InputArgs() []string { 58 return []string{"-f", "pulse", "-i", string(d)} 59 } 60 61 func (d PulseDevice) String() string { 62 return string(d) 63 } 64 65 func NewSession(cfg input.SessionConfig) (*execread.Session, error) { 66 dv, ok := cfg.Device.(PulseDevice) 67 if !ok { 68 return nil, fmt.Errorf("invalid device type %T", cfg.Device) 69 } 70 71 if cfg.FrameSize > 2 { 72 return nil, errors.New("channel count not supported, mono/stereo only") 73 } 74 75 args := []string{ 76 "parec", 77 "--format=float32le", 78 fmt.Sprintf("--rate=%.0f", cfg.SampleRate), 79 fmt.Sprintf("--channels=%d", cfg.FrameSize), 80 } 81 82 if dv != "" { 83 args = append(args, "-d", dv.String()) 84 } 85 86 return execread.NewSession(args, true, cfg), nil 87 }