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  }