diff --git a/case-lib/lib.sh b/case-lib/lib.sh index 10bc44b3..15d122ba 100644 --- a/case-lib/lib.sh +++ b/case-lib/lib.sh @@ -594,6 +594,7 @@ func_lib_enable_pipewire() systemctl --user start wireplumber.service systemctl --user daemon-reload + sleep 3 systemctl is-active --user --quiet pipewire{,-pulse}.{socket,service} && dlogi "Pipewire started" systemctl is-active --user --quiet wireplumber.service && dlogi "Wireplumber started" @@ -615,6 +616,7 @@ func_lib_disable_pipewire() sudo systemctl --global mask wireplumber.service sudo systemctl --global mask pipewire{,-pulse}.{socket,service} + sleep 1 if systemctl is-active --user --quiet wireplumber.service; then dlogi "Wireplumber not stopped"; else dlogi "Wireplumber stopped"; fi if systemctl is-active --user --quiet pipewire{,-pulse}.{socket,service}; then dlogi "Pipewire not stopped"; else dlogi "Pipewire stopped"; fi @@ -957,15 +959,9 @@ aplay_opts() # shellcheck disable=SC2086 tinyplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS -D "$card_nr" -d "$dev_nr" -i wav noise.wav elif [[ "$SOF_ALSA_TOOL" = "alsa" ]]; then - if [[ "$SOF_TEST_PIPEWIRE" == true ]]; then - dlogc "timeout -k $duration $duration aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS $*" # option -d doesn't work with pipewire so we need timeout - # shellcheck disable=SC2086 - timeout -k "$duration" "$duration" aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS "$@" - else - dlogc "aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS $*" - # shellcheck disable=SC2086 - aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS "$@" - fi + dlogc "aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS $*" + # shellcheck disable=SC2086 + aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS "$@" else die "Unknown ALSA tool: ${SOF_ALSA_TOOL}" fi @@ -982,20 +978,33 @@ arecord_opts() # shellcheck disable=SC2086 tinycap $SOF_ALSA_OPTS $SOF_ARECORD_OPTS "$file" -D "$card_nr" -d "$dev_nr" -c "$channel" -t "$duration" -r "$rate" -b "$format" elif [[ "$SOF_ALSA_TOOL" = "alsa" ]]; then - if [[ "$SOF_TEST_PIPEWIRE" == true ]]; then - dlogc "timeout -k $duration $duration arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS $*" # option -d doesn't work with pipewire so we need timeout - # shellcheck disable=SC2086 - timeout -k "$duration" "$duration" arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS "$@" - else - dlogc "arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS $*" - # shellcheck disable=SC2086 - arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS "$@" - fi + dlogc "arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS $*" + # shellcheck disable=SC2086 + arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS "$@" else die "Unknown ALSA tool: ${SOF_ALSA_TOOL}" fi } +# Get the ID of the first source of a given type, e.g. "Microphone" or "Audio codec". Print an empty line if ID not found. +get_id_of_pipewire_source() +{ + # $ wpctl status returns list of all endpoints managed by wireplumber. We use grep to get only lines after "Sources". + # Then we filter by given sink/source type, which returns something like this: + # │ * 48. sof-soundwire Microphone [vol: 0.40] (or without the * when it's not the current default) + # We filter out everything but ID, and only take the first line of the output (if there's more that one object of that type we ignore the rest) + + local object_name="$1" + object_id=$(wpctl status | grep "Sources" -A 10 | awk -v name="$object_name" 'tolower($0) ~ tolower(name) { sub(/\*/,""); sub(/\./,"",$2); print $2; exit }') + + # Check if object_id is a number + re='^[0-9]+$' + if [[ "$object_id" =~ $re ]] ; then + printf '%s' "$object_id" + fi + +} + # Get the ID of the first sink/source of a given type, e.g. "Speaker" or "Headphones". Print an empty line if ID not found. get_id_of_pipewire_endpoint() { @@ -1014,6 +1023,42 @@ get_id_of_pipewire_endpoint() } +# Get pipewire sink name for given alsa pcm +# Arguments: 1-alsa pcm, ex. hw:0,0 +set_default_pipewire_sink_for_alsa_pcm() +{ + card_id=$(echo "$1" | awk -F'[:,]' '{print $2}') + dev_id=$(echo "$1" | awk -F'[:,]' '{print $3}') + dlogi "card: $card_id, device: $dev_id" + + sink_name=$(pactl list sinks \ + | grep -B 20 "alsa.device = \"$dev_id\"" \ + | grep -B 16 "alsa.card = \"$card_id\"" \ + | grep "Name: alsa_output" \ + | cut -d' ' -f2-) + + dlogi "Setting default sink set to $sink_name" + pactl set-default-sink "$sink_name" +} + +# Get pipewire source name for given alsa pcm +# Arguments: 1-alsa pcm, ex. hw:0,0 +set_default_pipewire_source_for_alsa_pcm() +{ + card_id=$(echo "$1" | awk -F'[:,]' '{print $2}') + dev_id=$(echo "$1" | awk -F'[:,]' '{print $3}') + dlogi "card: $card_id, device: $dev_id" + + sink_name=$(pactl list sources \ + | grep -B 20 "alsa.device = \"$dev_id\"" \ + | grep -B 16 "alsa.card = \"$card_id\"" \ + | grep "Name: alsa_input" \ + | cut -d' ' -f2-) + + dlogi "Setting default source set to $sink_name" + pactl set-default-source "$sink_name" +} + die() { dloge "$@" diff --git a/test-case/check-alsabat.sh b/test-case/check-alsabat.sh index 644648ff..1caf6733 100755 --- a/test-case/check-alsabat.sh +++ b/test-case/check-alsabat.sh @@ -100,32 +100,103 @@ function __upload_wav_file done } -# check the PCMs before alsabat test -dlogi "check the PCMs before alsabat test" -aplay "-Dplug${pcm_p}" -d 1 /dev/zero -q || die "Failed to play on PCM: ${pcm_p}" -arecord "-Dplug${pcm_c}" -d 1 /dev/null -q || die "Failed to capture on PCM: ${pcm_c}" - -# alsabat test -# BT offload PCMs also support mono playback. -dlogc "alsabat -P$pcm_p --standalone -n $frames -r $rate -c $channel_p -f $format -F $frequency -k $sigmak" -alsabat "-P${pcm_p}" --standalone -n "${frames}" -c "${channel_p}" -r "${rate}" -f "${format}" -F "${frequency}" -k "${sigmak}" & playPID=$! - -# playback may have low latency, add one second delay to aviod recording zero at beginning. -sleep 1 - -# Select the first card -first_card_name=$(aplay -l | awk '/^card ([0-9]+)/ {print $3; exit}') -# dump amixer contents always. -# Good case amixer settings is for reference, bad case for debugging. -amixer -c "${first_card_name}" contents > "$LOG_ROOT"/amixer_settings.txt - -# We use different USB sound cards in CI, part of them only support 1 channel for capture, -# so make the channel as an option and config it in alsabat-playback.csv -dlogc "alsabat -C$pcm_c -c $channel_c -r $rate -f $format -F $frequency -k $sigmak" -alsabat "-C${pcm_c}" -c "${channel_c}" -r "${rate}" -f "${format}" -F "${frequency}" -k "${sigmak}" || { - # upload failed wav file - __upload_wav_file - exit 1 +# Set default pipewire sink and source +set_pcms_in_pipewire() +{ + set_default_pipewire_sink_for_alsa_pcm "$pcm_p" + set_default_pipewire_source_for_alsa_pcm "$pcm_c" +} + +check_the_pcms() +{ + aplay "-Dplug${pcm_p}" -d 1 /dev/zero -q || die "Failed to play on PCM: ${pcm_p}" + arecord "-Dplug${pcm_c}" -d 1 /dev/null -q || die "Failed to capture on PCM: ${pcm_c}" +} + +check_the_pcms_with_pipewire() +{ + aplay -D pipewire -d 1 /dev/zero -q || die "Failed to play on pipewire" + arecord -D pipewire -d 1 /dev/null -q || die "Failed to capture on pipewire" +} + +run_test_on_pipewire() +{ + # Set correct sink and source in pipewire + set_pcms_in_pipewire + + # check the PCMs before alsabat test + check_the_pcms_with_pipewire + + # alsabat tests + dlogc "alsabat -P pipewire --standalone -n $frames -r $rate -c $channel_p -f $format -F $frequency -k $sigmak" + alsabat -P pipewire --standalone -n "${frames}" -c "${channel_p}" -r "${rate}" -f "${format}" -F "${frequency}" -k "${sigmak}" & playPID=$! + + dlogc "alsabat -C pipewire --standalone -n $frames -c $channel_p -r $rate -f $format -F $frequency -k $sigmak" + alsabat -C pipewire --standalone -n "${frames}" -c "${channel_p}" -r "${rate}" -f "${format}" -F "${frequency}" -k "${sigmak}" || { + # upload failed wav file + __upload_wav_file + exit 1 + } +} + +run_test_on_alsa_direct_mode() +{ + # check the PCMs before alsabat test + check_the_pcms + + # alsabat test + # BT offload PCMs also support mono playback. + dlogc "alsabat -P$pcm_p --standalone -n $frames -r $rate -c $channel_p -f $format -F $frequency -k $sigmak" + alsabat "-P${pcm_p}" --standalone -n "${frames}" -c "${channel_p}" -r "${rate}" -f "${format}" -F "${frequency}" -k "${sigmak}" & playPID=$! + + # playback may have low latency, add one second delay to aviod recording zero at beginning. + sleep 1 + + # Select the first card + first_card_name=$(aplay -l | awk '/^card ([0-9]+)/ {print $3; exit}') + # dump amixer contents always. + # Good case amixer settings is for reference, bad case for debugging. + amixer -c "${first_card_name}" contents > "$LOG_ROOT"/amixer_settings.txt + + # We use different USB sound cards in CI, part of them only support 1 channel for capture, + # so make the channel as an option and config it in alsabat-playback.csv + dlogc "alsabat -C$pcm_c -c $channel_c -r $rate -f $format -F $frequency -k $sigmak" + alsabat "-C${pcm_c}" -c "${channel_c}" -r "${rate}" -f "${format}" -F "${frequency}" -k "${sigmak}" || { + # upload failed wav file + __upload_wav_file + exit 1 + } + + wait $playPID +} + +main() +{ + start_test + + if [ "$SOF_TEST_PIPEWIRE" == true ] && [[ "$TPLG" == *rt712* ]]; then + skip_test "Skipping: test not supported for RT712 configuration" + fi + + if [ "$pcm_p" = "" ]||[ "$pcm_c" = "" ]; + then + dloge "No playback or capture PCM is specified. Skip the alsabat test" + exit 2 + fi + + check_locale_for_alsabat + + logger_disabled || func_lib_start_log_collect + + set_alsa + + if [ "$SOF_TEST_PIPEWIRE" == true ]; then + run_test_on_pipewire + else + run_test_on_alsa_direct_mode + fi } -wait $playPID +{ + main "$@"; exit "$?" +} diff --git a/test-case/check-performance.sh b/test-case/check-performance.sh index 157eed19..3638db99 100755 --- a/test-case/check-performance.sh +++ b/test-case/check-performance.sh @@ -59,7 +59,7 @@ run_aplays() fi dlogi "Setting default sink to $sink_id: $sink_type" wpctl set-default "$sink_id" - aplay_opts -D pipewire /dev/zero -q & + aplay_opts -D pipewire /dev/zero -d "$duration" -q & aplay_num=$((aplay_num+1)) done } @@ -78,7 +78,7 @@ run_arecords() fi dlogi "Setting default source to $source_id: $source_type" wpctl set-default "$source_id" - arecord_opts -D pipewire /dev/null -q & + arecord_opts -D pipewire /dev/null -d "$duration" -q & arecord_num=$((arecord_num+1)) done }