Skip to content

Commit a867076

Browse files
committed
test: add option to test with pipewire
Signed-off-by: Emilia Kurdybelska <emiliax.kurdybelska@intel.com>
1 parent bf76a15 commit a867076

5 files changed

Lines changed: 168 additions & 26 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Some tests support these environment variables (work in progress):
6464
- SOF_ALSA_OPTS contains optional parameters passed on both play and record.
6565
- SOF_APLAY_OPTS and SOF_ARECORD_OPTS contain optional parameters passed additionally on play and record respectively.
6666
These options are applied to the selected tool (alsa or tinyalsa) based on the value of SOF_ALSA_TOOL
67+
= TEST_WITH_PIPEWIRE (default: false) allows to use pipewire instead of ALSA direct mode. Currently only works with check-performance.sh.
6768

6869
Warning, these environment variables do NOT support parameters
6970
with whitespace or globbing characters, in other words this does NOT

case-lib/hijack.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ function func_exit_handler()
1212

1313
dlogi "Starting func_exit_handler($exit_status)"
1414

15+
if [ "$TEST_WITH_PIPEWIRE" == true ]; then
16+
func_lib_disable_pipewire
17+
fi
18+
1519
# call trace
1620
if [ "$exit_status" -ne 0 ] ; then
1721
dloge "Starting ${FUNCNAME[0]}(), exit status=$exit_status, FUNCNAME stack:"

case-lib/lib.sh

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ minvalue() { printf '%d' $(( "$1" < "$2" ? "$1" : "$2" )); }
8383
#
8484
start_test()
8585
{
86+
if [ "$TEST_WITH_PIPEWIRE" == true ]; then
87+
func_lib_enable_pipewire
88+
fi
89+
8690
if is_subtest; then
8791
return 0
8892
fi
@@ -571,6 +575,55 @@ func_lib_check_sudo()
571575
}
572576
}
573577

578+
pipewire_unmask_manually()
579+
{
580+
services=("pipewire.service" "pipewire-pulse.service" "wireplumber.service" "pipewire.socket" "pipewire-pulse.socket")
581+
582+
for service in "${services[@]}"; do
583+
pw_service_path=$(systemctl --user show -p FragmentPath "$service")
584+
pw_service_path=${pw_service_path/"FragmentPath="/}
585+
pw_service_link=$(ls -l "$pw_service_path")
586+
if [[ "$pw_service_link" == *"/dev/null" ]]; then # Delete link if it points to /dev/null
587+
dlogi "Found ->/dev/null link: $pw_service_path, removing it"
588+
sudo rm "$pw_service_path"
589+
fi
590+
done
591+
}
592+
593+
start_pipewire_services()
594+
{
595+
systemctl --user daemon-reexec
596+
systemctl --user daemon-reload
597+
systemctl --user unmask pipewire{,-pulse}.{socket,service}
598+
systemctl --user start pipewire{,-pulse}.{socket,service}
599+
systemctl --user unmask wireplumber.service
600+
systemctl --user start wireplumber.service
601+
}
602+
603+
func_lib_enable_pipewire()
604+
{
605+
dlogi "Starting Pipewire..."
606+
# Sometimes unmasking does not work as expected, and we need to manually delete /dev/null links and try again
607+
start_pipewire_services || true
608+
pipewire_unmask_manually
609+
start_pipewire_services
610+
611+
# Wait for pipewire to start
612+
sleep 5s
613+
}
614+
615+
func_lib_disable_pipewire()
616+
{
617+
dlogi "Stopping Pipewire..."
618+
systemctl --user stop pipewire{,-pulse}.{socket,service}
619+
systemctl --user mask pipewire{,-pulse}.{socket,service}
620+
systemctl --user stop wireplumber.service
621+
systemctl --user mask wireplumber.service
622+
623+
# Wait for pipewire to stop
624+
sleep 2s
625+
}
626+
574627
systemctl_show_pulseaudio()
575628
{
576629
printf '\n'
@@ -908,9 +961,15 @@ aplay_opts()
908961
# shellcheck disable=SC2086
909962
tinyplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS -D "$card_nr" -d "$dev_nr" -i wav noise.wav
910963
elif [[ "$SOF_ALSA_TOOL" = "alsa" ]]; then
911-
dlogc "aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS $*"
912-
# shellcheck disable=SC2086
913-
aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS "$@"
964+
if [[ "$TEST_WITH_PIPEWIRE" == true ]]; then
965+
dlogc "timeout -k 60 30 aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS $*" # option -d doesn't work with pipewire so we need timeout
966+
# shellcheck disable=SC2086
967+
timeout -k 60 30 aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS "$@"
968+
else
969+
dlogc "aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS $*"
970+
# shellcheck disable=SC2086
971+
aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS "$@"
972+
fi
914973
else
915974
die "Unknown ALSA tool: ${SOF_ALSA_TOOL}"
916975
fi
@@ -927,9 +986,15 @@ arecord_opts()
927986
# shellcheck disable=SC2086
928987
tinycap $SOF_ALSA_OPTS $SOF_ARECORD_OPTS "$file" -D "$card_nr" -d "$dev_nr" -c "$channel" -t "$duration" -r "$rate" -b "$format"
929988
elif [[ "$SOF_ALSA_TOOL" = "alsa" ]]; then
930-
dlogc "arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS $*"
931-
# shellcheck disable=SC2086
932-
arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS "$@"
989+
if [[ "$TEST_WITH_PIPEWIRE" == true ]]; then
990+
dlogc "timeout -k 60 30 arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS $*" # option -d doesn't work with pipewire so we need timeout
991+
# shellcheck disable=SC2086
992+
timeout -k 60 30 arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS "$@"
993+
else
994+
dlogc "arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS $*"
995+
# shellcheck disable=SC2086
996+
arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS "$@"
997+
fi
933998
else
934999
die "Unknown ALSA tool: ${SOF_ALSA_TOOL}"
9351000
fi

test-case/check-performance.sh

Lines changed: 62 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,27 +51,69 @@ func_pipeline_export "$tplg" "type:any"
5151
aplay_num=0
5252
arecord_num=0
5353

54-
for idx in $(seq 0 $((PIPELINE_COUNT - 1)))
55-
do
56-
channel=$(func_pipeline_parse_value "$idx" channel)
57-
rate=$(func_pipeline_parse_value "$idx" rate)
58-
dev=$(func_pipeline_parse_value "$idx" dev)
59-
pcm=$(func_pipeline_parse_value "$idx" pcm)
60-
type=$(func_pipeline_parse_value "$idx" type)
61-
62-
# Currently, copier will convert bit depth to S32_LE despite what bit depth
63-
# is used in aplay, so make S32_LE as base bit depth for performance analysis.
64-
fmt=S32_LE
65-
66-
dlogi "Running (PCM: $pcm [$dev]<$type>) in background"
67-
if [ "$type" == "playback" ]; then
68-
aplay_opts -D "$dev" -c "$channel" -r "$rate" -f "$fmt" -d "$duration" /dev/zero -q &
69-
aplay_num=$((aplay_num+1))
70-
else
71-
arecord_opts -D "$dev" -c "$channel" -r "$rate" -f "$fmt" -d "$duration" /dev/null -q &
72-
arecord_num=$((arecord_num+1))
54+
if [ "$TEST_WITH_PIPEWIRE" == true ]; then
55+
56+
# aplay's for sinks
57+
pw_outputs_list=("Speaker" "Headphones" "HDMI")
58+
59+
for sink_type in "${pw_outputs_list[@]}"
60+
do
61+
sink_id=$(wpctl status | grep -A6 "Sinks" | grep -A3 -i "$sink_type" | tr -d '*' | awk '{print $2}' | tr -d '.' | head -n 1)
62+
if [ -z "$sink_id" ]; then
63+
dlogi "No $sink_type found, skipping to the next one"
64+
continue # skip if that device type isn't available
7365
fi
74-
done
66+
dlogi "Setting default sink to $sink_id: $sink_type"
67+
wpctl set-default "$sink_id"
68+
aplay_opts -Ddefault /dev/zero -q &
69+
aplay_num=$((aplay_num+1))
70+
done
71+
72+
# arecord's for sources
73+
pw_inputs_list=("Digital Microphone" "Headset Microphone" "SoundWire microphones")
74+
75+
for source_type in "${pw_inputs_list[@]}"
76+
do
77+
source_id=$(wpctl status | grep -A6 "Sources" | grep -A3 -i "$source_type" | tr -d '*' | awk '{print $2}' | tr -d '.' | head -n 1)
78+
if [ -z "$source_id" ]; then
79+
dlogi "No $source_type found, skipping to the next one"
80+
continue # skip if that device type isn't available
81+
fi
82+
dlogi "Setting default source to $source_id: $source_type"
83+
wpctl set-default "$source_id"
84+
arecord_opts -Ddefault /dev/zero -q &
85+
arecord_num=$((arecord_num+1))
86+
done
87+
88+
if [ $aplay_num == 0 ] && [ $arecord_num == 0 ]; then
89+
dloge "No sinks/sources to be tested found, exiting test"
90+
exit 1 #To be discussed: exit with 0 or 1 here?
91+
fi
92+
93+
else
94+
95+
for idx in $(seq 0 $((PIPELINE_COUNT - 1)))
96+
do
97+
channel=$(func_pipeline_parse_value "$idx" channel)
98+
rate=$(func_pipeline_parse_value "$idx" rate)
99+
dev=$(func_pipeline_parse_value "$idx" dev)
100+
pcm=$(func_pipeline_parse_value "$idx" pcm)
101+
type=$(func_pipeline_parse_value "$idx" type)
102+
103+
# Currently, copier will convert bit depth to S32_LE despite what bit depth
104+
# is used in aplay, so make S32_LE as base bit depth for performance analysis.
105+
fmt=S32_LE
106+
107+
dlogi "Running (PCM: $pcm [$dev]<$type>) in background"
108+
if [ "$type" == "playback" ]; then
109+
aplay_opts -D "$dev" -c "$channel" -r "$rate" -f "$fmt" -d "$duration" /dev/zero -q &
110+
aplay_num=$((aplay_num+1))
111+
else
112+
arecord_opts -D "$dev" -c "$channel" -r "$rate" -f "$fmt" -d "$duration" /dev/null -q &
113+
arecord_num=$((arecord_num+1))
114+
fi
115+
done
116+
fi
75117

76118
sleep 1 # waiting stable streaming of aplay/arecord
77119
dlogi "Number of aplay/arecord process started: $aplay_num, $arecord_num"

test-case/pipewire-wrapper.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/bash
2+
3+
##
4+
## Case Name: Wrapper to run a test case given with Pipewire
5+
## Preconditions:
6+
## Pipewire and Wireplumber are installed.
7+
## Description:
8+
## This script serves as a wrapper to execute a test case script using Pipewire.
9+
## It expects the test case script file name (without path) as the first parameter,
10+
## followed by other parameters required for that test case.
11+
## Case step:
12+
## 1. TEST_WITH_PIPEWIRE environment variable is set to true.
13+
## 2. The test case script is executed.
14+
## Expected result:
15+
## The test case script is executed using Pipewire.
16+
17+
set -e
18+
19+
# Ensure the test case script file name is provided
20+
if [ -z "$1" ]; then
21+
echo "Error: No test case script file name provided. Exiting..."
22+
exit 1
23+
fi
24+
25+
export TEST_WITH_PIPEWIRE=true
26+
27+
TESTDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
28+
29+
# shellcheck disable=SC2145
30+
[ -x "$TESTDIR/test-case/$(basename "$1")" ] && exec "$TESTDIR"/test-case/"$@"

0 commit comments

Comments
 (0)