순서가 지정된 목록에서 PulseAudio 수신기를 선택하고 해당 이름을 명령 입력으로 사용하는 스크립트

순서가 지정된 목록에서 PulseAudio 수신기를 선택하고 해당 이름을 명령 입력으로 사용하는 스크립트

오디오 소스와 Bluetooth 장치 사이에 PulseAudio 루프백 장치를 생성하는 bash 스크립트를 작성하고 싶습니다.

(컨텍스트 - 건너뛸 수 있음)

오디오 소스는 다음과 같은 방법으로 생성됩니다.

모듈 로드 모듈-jackdbus-감지 채널 = 2 sing_name = jack_bt_eq_outink_client_name = "PulseAudio - Bluetooth 수신기" source_name = jack_bt_in source_client_name = "PulseAudio - Bluetooth 소스" connect = false

# (이전 버전 - 15.0 이전)
#load-module module-jack-sinkink_name=jack_bt_eq_out client_name="PulseAudio - Bluetooth 수신기" 채널=2 connect=false
#load-module module-jack-source source_name=jack_bt_in client_name="PulseAudio - Bluetooth 소스" 채널=2 connect=false

위에서 볼 수 있듯이 오디오 수신기도 생성됩니다. 목표는 Jack의 이퀄라이저를 통과하여 오디오 소스로 출력한 다음 재생을 위해 오디오를 실제 Bluetooth 하드웨어로 리디렉션하는 것입니다.

카라의 스크린샷

지금까지 내 스크립트 (관련 부분) 는 다음과 같습니다.

echo "Device must be connected...";
echo "Choose a device:";
## WIP
# (present device list - 'bluez.alias')
# (wait for input)
# (assign 'sink_name'- without enclosing <>)

pacmd load-module module-loopback source=jack_bt_in sink=[TODO:sink_name] rate=48000 sink_dont_move=true latency_msec=240 max_latency_msec=250;

내가 원하는 것은 PulseAudio에서 사용할 수 있는 Bluetooth 오디오 장치 목록을 다음 형식으로 사용자에게 표시하는 것입니다.

  1. 비타민 T1L을 사용하세요
  2. JBL GO 2
  3. (...)

해당 장치 목록과 PulseAudio 수신기 이름은 다음을 통해 얻을 수 있습니다.

$ pacmd list-sinks | grep "bluez"
    name: <bluez_sink.00_00_00_00_0D_91.a2dp_sink>
    driver: <module-bluez5-device.c>
    card: 8 <bluez_card.00_00_00_00_0D_91>
        device.api = "bluez"
        bluez.path = "/org/bluez/hci0/dev_00_00_00_00_0D_91"
        bluez.class = "0x240404"
        bluez.alias = "AWEI T1L"
    name: <bluez_sink.F8_5C_7D_15_1D_47.a2dp_sink>
    driver: <module-bluez5-device.c>
    card: 9 <bluez_card.F8_5C_7D_15_1D_47>
        device.api = "bluez"
        bluez.path = "/org/bluez/hci0/dev_F8_5C_7D_15_1D_47"
        bluez.class = "0x200414"
        bluez.alias = "JBL GO 2"

문제는 "모듈 루프백"이 올바르게 로드되도록 주변 문자 와 문자를 bluez.alias제거하여 값(표시용)과 수신자 이름을 얻기 위해 위 명령의 출력을 구문 분석하는 방법입니다.<>

지금까지 를 사용하여 장치 목록을 얻을 수 있지만 순서가 pacmd list-sinks | grep "bluez.alias" | cut -d \" -f 2지정된 목록으로 렌더링하는 방법을 잘 모르겠습니다. 어쨌든 수신기 이름을 얻으려면 두 번째 명령이 필요합니다. 이는 불안정하고 이상적이지 않습니다. 특히 쿼리 사이에 장치 연결이 끊어질 수 있으므로 단일 명령을 사용하여 장치 별칭과 해당 수신자 이름을 가져와 배열에 저장하고 싶습니다.

답변1

bash에 내장된 정규식을 사용하여 이를 수행하는 방법은 다음과 같습니다. cat sinks.txt다음으로 바꾸고 select 문에 명령을 추가하면 됩니다 pacmd list-sinks.pacmd load-module ...

#!/bin/bash
set -eu

aliases=()
declare -A mapping

while read -r line; do
    if [[ $line =~ ^name:' <'([^>]*)'>' ]]; then
        name=${BASH_REMATCH[1]}
    elif [[ $line =~ ^bluez.alias' = "'([^\"]*)'"' ]]; then
        aliases+=("${BASH_REMATCH[1]}")
        mapping[${BASH_REMATCH[1]}]=$name
    fi
done < <(cat sinks.txt)

PS3="Select device: "
select alias in "${aliases[@]}"; do
    echo "Connecting sink ${mapping[$alias]}..."
    break
done

장치 별칭을 임의 순서로 렌더링할 수 있다면 별칭 배열이 필요하지 않지만 순서가 중요하다고 생각합니다.

사용자 정의 메뉴 형식의 경우 select 문을 다음으로 바꿉니다.

while :; do
    for ((i = 0; i < ${#aliases[@]}; ++i)); do
        printf "%s. %s\n" "$((i+1))" "${aliases[i]}"
    done
    read -p 'Select device: '
    [[ $REPLY != *[^0-9]* && $REPLY -gt 0 && $REPLY -le ${#aliases[@]} ]] && break
    echo "Invalid choice."
done
echo "Connecting sink ${mapping[${aliases[REPLY-1]}]}..."

또한 메뉴에서 유효한 숫자만 허용하도록 일부 입력 유효성 검사도 추가했습니다.

관련 정보