From 351a5190c953f8eeaa7bdea1328e6b1179bbbbce Mon Sep 17 00:00:00 2001 From: Tilman Kranz Date: Mon, 9 Oct 2023 20:01:33 +0200 Subject: [PATCH 1/3] run two tunnels, which is probably wrong (leads to timeouts on local host) --- pulseaudio-tcp | 267 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 231 insertions(+), 36 deletions(-) diff --git a/pulseaudio-tcp b/pulseaudio-tcp index af7fb15..de06562 100644 --- a/pulseaudio-tcp +++ b/pulseaudio-tcp @@ -94,6 +94,70 @@ do_setup() { fi done + inbound=${inbound:-true} + + while true ; do + if "$inbound" ; then + prompt="Y/n" + else + prompt="y/N" + fi + + read -r -p "Enable inbound audio ($prompt): " inbound_in + + case "$inbound_in" in + "") + if test -n "$inbound" ; then + inbound_in=$inbound + break 2 + fi + ;; + y|Y) + inbound_in=true + break 2 + ;; + n|N) + inbound_in=false + break 2 + ;; + *) + echo "ERROR: Please type \"y\" or \"n\"." >&2 + ;; + esac + done + + outbound=${outbound:-true} + + while true ; do + if "$outbound" ; then + prompt="Y/n" + else + prompt="y/N" + fi + + read -r -p "Enable outbound audio ($prompt): " outbound_in + + case "$outbound_in" in + "") + if test -n "$outbound" ; then + outbound_in=$outbound + break 2 + fi + ;; + y|Y) + outbound_in=true + break 2 + ;; + n|N) + outbound_in=false + break 2 + ;; + *) + echo "ERROR: Please type \"y\" or \"n\"." >&2 + ;; + esac + done + cat > "$config" << EOF # Configuration file for pulseaudio-tcp # Generated on $(LC_ALL=C date) by $USER using $0 @@ -103,40 +167,78 @@ remote_ip="$remote_ip_in" # Username on remote host remote_user="$remote_user_in" + +# Enable inbound audio from $remote_user @$remote_ip? +inbound=$inbound_in + +# Enable outbound audio to $remote_user @$remote_ip? +outbound=$outbound_in EOF } # Check if SSH port forwarding is running check_pa_ssh() { - for pid in $(pidof ssh) ; do - grep -Fq $USER-pulseaudio /proc/"$pid"/cmdline && return 0 - done + if ! "$outbound" && ! "$inbound" ; then + return 0 + else + for pid in $(pidof ssh) ; do + if grep -Fq $USER-pulseaudio /proc/"$pid"/cmdline ; then + if "$outbound" ; then + grep -Fq -e -L /proc/"$pid"/cmdline || { + echo "ERROR: No SSH port forwarding to remote server for outbound audio established." >&2 + return 1 ; + } + fi - return 1 + if "$inbound" ; then + grep -Fq -e -L /proc/"$pid"/cmdline || { + echo "ERROR: No SSH port forwarding from remote server for inbound audio established." >&2 + return 1 ; + } + fi + fi + done + + echo "ERROR: No SSH port forwarding established." >&2 + return 1 + fi } # Perform status operation do_status() { rv=0 - if ! _ssh pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then - echo "ERROR: PulseAudio module \"module-native-protocol-tcp\" is not loaded on remote_ip=$remote_ip." >&2 - rv=1 - fi - if ! check_pa_ssh ; then - echo "ERROR: SSH port forwarding to remote_ip=$remote_ip is not running." >&2 rv=1 fi - if ! pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then - echo "ERROR: PulseAudio module \"module-tunnel-sink\" is not loaded." >&2 - rv=1 + if "$outbound" ; then + if ! _ssh pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then + echo "ERROR: PulseAudio module \"module-native-protocol-tcp\" is not loaded on remote_ip=$remote_ip." >&2 + rv=1 + fi + + if ! pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then + echo "ERROR: PulseAudio module \"module-tunnel-sink\" is not loaded." >&2 + rv=1 + fi + + if ! pactl get-default-sink | grep -Fq "tunnel-sink.tcp:127.0.0.1" ; then + echo "ERROR: \"tunnel-sink.tcp:127.0.0.1\" is not the default PulseAudio sink." >&2 + rv=1 + fi fi - if ! pactl get-default-sink | grep -Fq "tunnel-sink.tcp:127.0.0.1" ; then - echo "ERROR: \"tunnel-sink.tcp:127.0.0.1\" is not the default PulseAudio sink." >&2 - rv=1 + if "$inbound" ; then + if ! pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then + echo "ERROR: PulseAudio module \"module-native-protocol-tcp\" is not loaded." >&2 + rv=1 + fi + + if ! _ssh pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then + echo "ERROR: PulseAudio module \"module-tunnel-sink\" is not loaded on remote_ip=$remote_ip." >&2 + rv=1 + fi fi if test "$rv" -eq 0 ; then @@ -158,7 +260,7 @@ sync_pa_cookie() { } # Enable PulseAudio TCP tunnel server on remote host -enable_pa_tunnel_server() { +enable_remote_pa_tunnel_server() { if _ssh pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then echo "INFO: PulseAudio module \"module-native-protocol-tcp\" already loaded on remote_ip=$remote_ip." >&2 return 0 @@ -171,13 +273,33 @@ enable_pa_tunnel_server() { fi } +# Enable PulseAudio TCP tunnel server on local host +enable_local_pa_tunnel_server() { + if pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then + echo "INFO: PulseAudio module \"module-native-protocol-tcp\" already loaded." >&2 + return 0 + elif pactl load-module module-native-protocol-tcp listen=127.0.0.1 auth-ip-acl=127.0.0.1 ; then + echo "INFO: Loaded PulseAudio module \"module-native-protocol-tcp\"." >&2 + return 0 + else + echo "ERROR: Unable to load PulseAudio module \"module-native-protocol-tcp\"." >&2 + return 1 + fi +} + # Establish SSH port forwarding to PulseAudio TCP server on remote host establish_ssh_portforward() { - _ssh -fNT -L 127.0.0.1:4713:127.0.0.1:4713 + if "$outbound" && ! "$inbound" ; then + _ssh -fNT -L 127.0.0.1:4713:127.0.0.1:4713 + elif "$inbound" && ! "$outbound" ; then + _ssh -fNT -R 127.0.0.1:4713:127.0.0.1:4713 + elif "$outbound" && "$inbound" ; then + _ssh -fNT -L 127.0.0.1:4713:127.0.0.1:4713 -R 127.0.0.1:4713:127.0.0.1:4713 + fi } # Enable tunnel sink on local host -enable_pa_tunnel_sink() { +enable_local_pa_tunnel_sink() { if pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then echo "INFO: PulseAudio module \"module-tunnel-sink\" already loaded." >&2 return 0 @@ -190,8 +312,22 @@ enable_pa_tunnel_sink() { fi } +# Enable tunnel sink on remote host +enable_remote_pa_tunnel_sink() { + if _ssh pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then + echo "INFO: PulseAudio module \"module-tunnel-sink\" already loaded on remote_ip=$remote_ip." >&2 + return 0 + elif _ssh pactl load-module module-tunnel-sink server=tcp:127.0.0.1 ; then + echo "INFO: Loaded PulseAudio module \"module-tunnel-sink\" on remote_ip=$remote_ip." >&2 + return 0 + else + echo "ERROR: Unable to load PulseAudio module \"module-tunnel-sink\" on remote_ip=$remote_ip." >&2 + return 1 + fi +} + # Set tunnel sink as default sink on local host -set_pa_tunnel_sink_as_default() { +set_local_pa_tunnel_sink_as_default() { if pactl set-default-sink tunnel-sink.tcp:127.0.0.1 ; then echo "INFO: Set \"tunnel-sink.tcp:127.0.0.1\" as default PulseAudio sink." >&2 return 0 @@ -204,16 +340,48 @@ set_pa_tunnel_sink_as_default() { # Perform start operation do_start() { sync_pa_cookie || return 1 - enable_pa_tunnel_server || return 1 establish_ssh_portforward || return 1 - enable_pa_tunnel_sink || return 1 - set_pa_tunnel_sink_as_default || return 1 + + if "$outbound" ; then + enable_remote_pa_tunnel_server || return 1 + enable_local_pa_tunnel_sink || return 1 + set_local_pa_tunnel_sink_as_default || return 1 + fi + + if "$inbound" ; then + enable_local_pa_tunnel_server || return 1 + enable_remote_pa_tunnel_sink || return 1 + fi return 0 } +# Remove PulseAudio TCP tunnel sink on remote host +remove_remote_pa_tunnel_sink() { + if ! _ssh pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then + echo "INFO: PulseAudio module \"module-tunnel-sink\" is not loaded on remote_ip=$remote_ip." >&2 + return 0 + elif ! _ssh pactl list sinks | grep -Fq "tunnel-sink.tcp:127.0.0.1" ; then + echo "INFO: No PulseAudio tunnel sink to 127.0.0.1 exists on remote_ip=$remote_ip." >&2 + return 0 + else + owner_module=$( + _ssh pactl --format json list sinks 2>/dev/null | \ + jq '.[] | select(.name=="tunnel-sink.tcp:127.0.0.1") | .owner_module' -r + ) + + if ! _ssh pactl unload-module "$owner_module" ; then + echo "ERROR: Could not unload owner module $owner_module of PulseAudio sink \"tunnel-sink.tcp:127.0.0.1\" on remote_ip=$remote_ip." >&2 + return 1 + else + echo "INFO: Unloaded owner module $owner_module of PulseAudio sink \"tunnel-sink.tcp:127.0.0.1\" on remote_ip=$remote_ip." >&2 + return 0 + fi + fi +} + # Remove PulseAudio TCP tunnel sink on local host -remove_pa_tunnel_sink() { +remove_local_pa_tunnel_sink() { if ! pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then echo "INFO: PulseAudio module \"module-tunnel-sink\" is not loaded." >&2 return 0 @@ -236,17 +404,22 @@ remove_pa_tunnel_sink() { fi } -# Terminate SSH portforwarding session -terminate_ssh_portforward() { - for pid in $(pidof ssh) ; do - if grep -Fq $USER-pulseaudio /proc/"$pid"/cmdline ; then - kill -TERM "$pid" - fi - done +# Stop PulseAudio TCP tunnel server on local host. +disable_local_pa_tunnel_server() { + if ! pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then + echo "INFO: PulseAudio module \"module-native-protocol-tcp\" not loaded." >&2 + return 0 + elif ! pactl unload-module module-native-protocol-tcp ; then + echo "ERROR: Could not unload PulseAudio module \"module-native-protocol-tcp\"." >&2 + return 1 + else + echo "INFO: Unloaded PulseAudio module \"module-native-protocol-tcp\"." >&2 + return 0 + fi } # Stop PulseAudio TCP tunnel server on remote host. -disable_pa_tunnel_server() { +disable_remote_pa_tunnel_server() { if ! _ssh pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then echo "INFO: PulseAudio module \"module-native-protocol-tcp\" not loaded on remote_ip=$remote_ip." >&2 return 0 @@ -259,11 +432,28 @@ disable_pa_tunnel_server() { fi } +# Terminate SSH portforwarding session +terminate_ssh_portforward() { + for pid in $(pidof ssh) ; do + if grep -Fq $USER-pulseaudio /proc/"$pid"/cmdline ; then + kill -TERM "$pid" + fi + done +} + # Perform stop operation do_stop() { - remove_pa_tunnel_sink || return 1 + if "$outbound" ; then + remove_local_pa_tunnel_sink || return 1 + disable_remote_pa_tunnel_server || return 1 + fi + + if "$inbound" ; then + remove_remote_pa_tunnel_sink || return 1 + disable_local_pa_tunnel_server || return 1 + fi + terminate_ssh_portforward || return 1 - disable_pa_tunnel_server || return 1 return 0 } @@ -316,7 +506,7 @@ else ""|-h|--help) cat << EOF Setup and run encrypted connection to remote PulseAudio/Pipewire server -Usage: $0 setup|start|stop|status +Usage: $0 restart|setup|start|status|stop EOF rv=0 ;; @@ -332,12 +522,17 @@ EOF do_stop rv=$? ;; + restart) + do_stop + do_start + rv=$? + ;; status) do_status rv=$? ;; *) - echo "ERROR: Usage: $0 setup|start|stop|status" >&2 + echo "ERROR: Usage: $0 restart|setup|start|status|stop" >&2 rv=1 ;; esac From 08cfa114513336992255456e2fc1338b725681e1 Mon Sep 17 00:00:00 2001 From: Tilman Kranz Date: Tue, 10 Oct 2023 02:48:13 +0200 Subject: [PATCH 2/3] implement inbound audio using tunnel source --- pulseaudio-tcp | 158 ++++++++++++++++--------------------------------- 1 file changed, 52 insertions(+), 106 deletions(-) diff --git a/pulseaudio-tcp b/pulseaudio-tcp index de06562..fbc14b0 100644 --- a/pulseaudio-tcp +++ b/pulseaudio-tcp @@ -178,30 +178,17 @@ EOF # Check if SSH port forwarding is running check_pa_ssh() { - if ! "$outbound" && ! "$inbound" ; then - return 0 - else - for pid in $(pidof ssh) ; do - if grep -Fq $USER-pulseaudio /proc/"$pid"/cmdline ; then - if "$outbound" ; then - grep -Fq -e -L /proc/"$pid"/cmdline || { - echo "ERROR: No SSH port forwarding to remote server for outbound audio established." >&2 - return 1 ; - } - fi + for pid in $(pidof ssh) ; do + if grep -Fq $USER-pulseaudio /proc/"$pid"/cmdline ; then + grep -Fq -e -L /proc/"$pid"/cmdline || { + echo "ERROR: No SSH port forwarding to remote server is established." >&2 + return 1 ; + } + fi + done - if "$inbound" ; then - grep -Fq -e -L /proc/"$pid"/cmdline || { - echo "ERROR: No SSH port forwarding from remote server for inbound audio established." >&2 - return 1 ; - } - fi - fi - done - - echo "ERROR: No SSH port forwarding established." >&2 - return 1 - fi + echo "ERROR: No SSH is established." >&2 + return 1 } # Perform status operation @@ -212,12 +199,12 @@ do_status() { rv=1 fi - if "$outbound" ; then - if ! _ssh pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then - echo "ERROR: PulseAudio module \"module-native-protocol-tcp\" is not loaded on remote_ip=$remote_ip." >&2 - rv=1 - fi + if ! _ssh pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then + echo "ERROR: PulseAudio module \"module-native-protocol-tcp\" is not loaded on remote_ip=$remote_ip." >&2 + rv=1 + fi + if "$outbound" ; then if ! pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then echo "ERROR: PulseAudio module \"module-tunnel-sink\" is not loaded." >&2 rv=1 @@ -230,13 +217,8 @@ do_status() { fi if "$inbound" ; then - if ! pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then - echo "ERROR: PulseAudio module \"module-native-protocol-tcp\" is not loaded." >&2 - rv=1 - fi - - if ! _ssh pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then - echo "ERROR: PulseAudio module \"module-tunnel-sink\" is not loaded on remote_ip=$remote_ip." >&2 + if ! pactl list modules | grep -Fq "Name: module-tunnel-source" ; then + echo "ERROR: PulseAudio module \"module-tunnel-source\" is not loaded." >&2 rv=1 fi fi @@ -259,6 +241,11 @@ sync_pa_cookie() { fi } +# Establish SSH port forwarding to PulseAudio TCP server on remote host +establish_ssh_portforward() { + _ssh -fNT -L 127.0.0.1:4713:127.0.0.1:4713 +} + # Enable PulseAudio TCP tunnel server on remote host enable_remote_pa_tunnel_server() { if _ssh pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then @@ -273,31 +260,6 @@ enable_remote_pa_tunnel_server() { fi } -# Enable PulseAudio TCP tunnel server on local host -enable_local_pa_tunnel_server() { - if pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then - echo "INFO: PulseAudio module \"module-native-protocol-tcp\" already loaded." >&2 - return 0 - elif pactl load-module module-native-protocol-tcp listen=127.0.0.1 auth-ip-acl=127.0.0.1 ; then - echo "INFO: Loaded PulseAudio module \"module-native-protocol-tcp\"." >&2 - return 0 - else - echo "ERROR: Unable to load PulseAudio module \"module-native-protocol-tcp\"." >&2 - return 1 - fi -} - -# Establish SSH port forwarding to PulseAudio TCP server on remote host -establish_ssh_portforward() { - if "$outbound" && ! "$inbound" ; then - _ssh -fNT -L 127.0.0.1:4713:127.0.0.1:4713 - elif "$inbound" && ! "$outbound" ; then - _ssh -fNT -R 127.0.0.1:4713:127.0.0.1:4713 - elif "$outbound" && "$inbound" ; then - _ssh -fNT -L 127.0.0.1:4713:127.0.0.1:4713 -R 127.0.0.1:4713:127.0.0.1:4713 - fi -} - # Enable tunnel sink on local host enable_local_pa_tunnel_sink() { if pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then @@ -312,16 +274,16 @@ enable_local_pa_tunnel_sink() { fi } -# Enable tunnel sink on remote host -enable_remote_pa_tunnel_sink() { - if _ssh pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then - echo "INFO: PulseAudio module \"module-tunnel-sink\" already loaded on remote_ip=$remote_ip." >&2 +# Enable tunnel source on local host +enable_local_pa_tunnel_source() { + if pactl list modules | grep -Fq "Name: module-tunnel-source" ; then + echo "INFO: PulseAudio module \"module-tunnel-source\" already loaded." >&2 return 0 - elif _ssh pactl load-module module-tunnel-sink server=tcp:127.0.0.1 ; then - echo "INFO: Loaded PulseAudio module \"module-tunnel-sink\" on remote_ip=$remote_ip." >&2 + elif pactl load-module module-tunnel-source server=tcp:127.0.0.1 ; then + echo "INFO: Loaded PulseAudio module \"module-tunnel-source\"." >&2 return 0 else - echo "ERROR: Unable to load PulseAudio module \"module-tunnel-sink\" on remote_ip=$remote_ip." >&2 + echo "ERROR: Unable to load PulseAudio module \"module-tunnel-source\"." >&2 return 1 fi } @@ -341,45 +303,20 @@ set_local_pa_tunnel_sink_as_default() { do_start() { sync_pa_cookie || return 1 establish_ssh_portforward || return 1 + enable_remote_pa_tunnel_server || return 1 if "$outbound" ; then - enable_remote_pa_tunnel_server || return 1 enable_local_pa_tunnel_sink || return 1 set_local_pa_tunnel_sink_as_default || return 1 fi if "$inbound" ; then - enable_local_pa_tunnel_server || return 1 - enable_remote_pa_tunnel_sink || return 1 + enable_local_pa_tunnel_source || return 1 fi return 0 } -# Remove PulseAudio TCP tunnel sink on remote host -remove_remote_pa_tunnel_sink() { - if ! _ssh pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then - echo "INFO: PulseAudio module \"module-tunnel-sink\" is not loaded on remote_ip=$remote_ip." >&2 - return 0 - elif ! _ssh pactl list sinks | grep -Fq "tunnel-sink.tcp:127.0.0.1" ; then - echo "INFO: No PulseAudio tunnel sink to 127.0.0.1 exists on remote_ip=$remote_ip." >&2 - return 0 - else - owner_module=$( - _ssh pactl --format json list sinks 2>/dev/null | \ - jq '.[] | select(.name=="tunnel-sink.tcp:127.0.0.1") | .owner_module' -r - ) - - if ! _ssh pactl unload-module "$owner_module" ; then - echo "ERROR: Could not unload owner module $owner_module of PulseAudio sink \"tunnel-sink.tcp:127.0.0.1\" on remote_ip=$remote_ip." >&2 - return 1 - else - echo "INFO: Unloaded owner module $owner_module of PulseAudio sink \"tunnel-sink.tcp:127.0.0.1\" on remote_ip=$remote_ip." >&2 - return 0 - fi - fi -} - # Remove PulseAudio TCP tunnel sink on local host remove_local_pa_tunnel_sink() { if ! pactl list modules | grep -Fq "Name: module-tunnel-sink" ; then @@ -404,17 +341,27 @@ remove_local_pa_tunnel_sink() { fi } -# Stop PulseAudio TCP tunnel server on local host. -disable_local_pa_tunnel_server() { - if ! pactl list modules | grep -Fq "Name: module-native-protocol-tcp" ; then - echo "INFO: PulseAudio module \"module-native-protocol-tcp\" not loaded." >&2 +# Remove PulseAudio TCP tunnel source on local host +remove_local_pa_tunnel_source() { + if ! pactl list modules | grep -Fq "Name: module-tunnel-source" ; then + echo "INFO: PulseAudio module \"module-tunnel-source\" is not loaded." >&2 + return 0 + elif ! pactl list sources | grep -Fq "tunnel-source.tcp:127.0.0.1" ; then + echo "INFO: No PulseAudio tunnel source from 127.0.0.1 exists." >&2 return 0 - elif ! pactl unload-module module-native-protocol-tcp ; then - echo "ERROR: Could not unload PulseAudio module \"module-native-protocol-tcp\"." >&2 - return 1 else - echo "INFO: Unloaded PulseAudio module \"module-native-protocol-tcp\"." >&2 - return 0 + owner_module=$( + pactl --format json list sources 2>/dev/null | \ + jq '.[] | select(.name=="tunnel-source.tcp:127.0.0.1") | .owner_module' -r + ) + + if ! pactl unload-module "$owner_module" ; then + echo "ERROR: Could not unload owner module $owner_module of PulseAudio source \"tunnel-source.tcp:127.0.0.1\"." >&2 + return 1 + else + echo "INFO: Unloaded owner module $owner_module of PulseAudio source \"tunnel-source.tcp:127.0.0.1\"." >&2 + return 0 + fi fi } @@ -445,14 +392,13 @@ terminate_ssh_portforward() { do_stop() { if "$outbound" ; then remove_local_pa_tunnel_sink || return 1 - disable_remote_pa_tunnel_server || return 1 fi if "$inbound" ; then - remove_remote_pa_tunnel_sink || return 1 - disable_local_pa_tunnel_server || return 1 + remove_local_pa_tunnel_source || return 1 fi + disable_remote_pa_tunnel_server || return 1 terminate_ssh_portforward || return 1 return 0 From 09c91bade9aebc269ae80f9460cd217cfbcce511 Mon Sep 17 00:00:00 2001 From: Tilman Kranz Date: Tue, 10 Oct 2023 02:56:02 +0200 Subject: [PATCH 3/3] update documentation to bidirectional operation --- README.md | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d8fcc3b..0ce9e7d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# pulseaudio-tcp - Redirect PulseAudio to Remote Computer +# pulseaudio-tcp - Redirect PulseAudio to and from Remote Computer ## Requirements @@ -12,7 +12,10 @@ ### Installation on Client Playback Host * pulseaudio-tcp should be installed on a computer running PulseAudio or Pipewire with PulseAudio compatibility. -* The computer pulseaudio-tcp is installed on ("local host") should use use a remote computer that has speakers attached ("remote host") for playback. +* The computer pulseaudio-tcp is installed on ("local host") should use use a remote computer ("remote host") for playback. + - This is refered to as "outbound" audio. +* The local host should receive audio from the remote host for recording. + - This is refered to as "inbound" audio. * The IP address and username of the remote host should be known. ### SSH to User Session on Remote Host @@ -33,7 +36,7 @@ sudo make install ## Usage -### Configuration +### Setup Procedure As regular user on local host: @@ -41,19 +44,37 @@ As regular user on local host: pulseadio-tcp setup ``` -### Start service +The following questions will be asked: + +* IP address of remote host. +* Name of user on remote host running PulseAudio/Pipewire. +* Enable inbound audio. +* Enable outbound audio. + +### Configuration File + +The setup procedure writes a configuration file `$HOME/.config/pulseaudio-tcp/config.inc.sh`: + +``` +remote_ip="192.168.1.166" +remote_user="remoteuser" +inbound=true +outbound=true +``` + +### Starting the Service ```shell pulseadio-tcp start ``` -### Stop service +### Stopping the Service ```shell pulseadio-tcp stop ``` -### Check if service is running +### Checking if the Service is running ```shell pulseadio-tcp status