diff --git a/src/.local/bin/bridge.sh b/src/.local/bin/bridge.sh index 4aacf5a..aa5d724 100755 --- a/src/.local/bin/bridge.sh +++ b/src/.local/bin/bridge.sh @@ -1,6 +1,16 @@ #!/bin/sh -# Awful script I made to bridge calls from two services while also piping in audio +# PulseAudio script to categorise audio streams +# +# - playing music while recording a call +# - piping sound files into a call via virtual mic +# +# Use the -b switch for bridging +# - connect calls from different applications + + + +# Important settings # Your real mic (pactl list short sources) mic="alsa_input.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.mono-fallback" @@ -8,55 +18,76 @@ mic="alsa_input.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.mono-fallback" # Output sound to this sink (pactl list short sinks) out="alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.analog-stereo" -# Name of the virtual mic output (combined mic and shared media) + + +# Naming settings + +# Virtual mic for both voice and media virt_mic="virtual_mic" virt_mic_desc="Virtual\ mic" -# Name of the media input sink +# Input for media to pipe to call media_in="media_in" media_in_desc="Media\ input" -# Name of the sink whose monitor will be used as the mic for the first call +# Virtual mic for call c1_in="c1_in" -c1_in_desc="C1\ input" +c1_in_desc="Call\ input" -# Name of the sink where the first call will be output +# Output of call c1_out="c1_out" -c1_out_desc="C1\ output" +c1_out_desc="Call\ output" -# Name of the sink whose monitor will be used as the mic for the second call +# Virtual mic for bridged call c2_in="c2_in" c2_in_desc="C2\ input" -# Name of the sink where the second call will be output +# Output of bridged call c2_out="c2_out" c2_out_desc="C2\ output" -# Create all the sinks -pactl load-module module-null-sink sink_name="$media_in" sink_properties=device.description="'$media_in_desc'" -pactl load-module module-null-sink sink_name="$virt_mic" sink_properties=device.description="'$virt_mic_desc'" + +MODE="normal" +while getopts "b" o; do + case "${o}" in + b) MODE="bridge" ;; + esac +done + +# Set up call input/output +# Create sinks pactl load-module module-null-sink sink_name="$c1_out" sink_properties=device.description="'$c1_out_desc'" pactl load-module module-null-sink sink_name="$c1_in" sink_properties=device.description="'$c1_in_desc'" -pactl load-module module-null-sink sink_name="$c2_out" sink_properties=device.description="'$c2_out_desc'" -pactl load-module module-null-sink sink_name="$c2_in" sink_properties=device.description="'$c2_in_desc'" +# Output to real speakers +pactl load-module module-loopback source="$c1_out".monitor sink="$out" -# Make connections between all sinks - -# Loop back real mic to the virtual mic -pactl load-module module-loopback source="$mic" sink="$virt_mic" - -# Loop back media input to virtual mic -pactl load-module module-loopback source="$media_in".monitor sink="$virt_mic" -# Loop back media input to regular audio output +# Set up media input +# Create sink +pactl load-module module-null-sink sink_name="$media_in" sink_properties=device.description="'$media_in_desc'" +# Output to real speakers pactl load-module module-loopback source="$media_in".monitor sink="$out" -# Loop combined output to both calls' inputs +# Set up virtual mic +# Create sink +pactl load-module module-null-sink sink_name="$virt_mic" sink_properties=device.description="'$virt_mic_desc'" +# Loop in real mic +pactl load-module module-loopback source="$mic" sink="$virt_mic" +# Loop in media input +pactl load-module module-loopback source="$media_in".monitor sink="$virt_mic" +# Output to call input pactl load-module module-loopback source="$virt_mic".monitor sink="$c1_in" -pactl load-module module-loopback source="$virt_mic".monitor sink="$c2_in" -# Loop the calls' outputs to each other's inputs and also local output -pactl load-module module-loopback source="$c1_out".monitor sink="$out" -pactl load-module module-loopback source="$c1_out".monitor sink="$c2_in" -pactl load-module module-loopback source="$c2_out".monitor sink="$out" -pactl load-module module-loopback source="$c2_out".monitor sink="$c1_in" +# Bridging +if [ $MODE = "bridge" ]; then + # Create bridged call input/output sinks + pactl load-module module-null-sink sink_name="$c2_out" sink_properties=device.description="'$c2_out_desc'" + pactl load-module module-null-sink sink_name="$c2_in" sink_properties=device.description="'$c2_in_desc'" + # Loop in virtual mic + pactl load-module module-loopback source="$virt_mic".monitor sink="$c2_in" + # Output to real speakers + pactl load-module module-loopback source="$c2_out".monitor sink="$out" + # Connect calls into each other + pactl load-module module-loopback source="$c1_out".monitor sink="$c2_in" + pactl load-module module-loopback source="$c2_out".monitor sink="$c1_in" +fi diff --git a/src/.local/bin/pulse_move.sh b/src/.local/bin/pulse_move.sh new file mode 100755 index 0000000..da28a36 --- /dev/null +++ b/src/.local/bin/pulse_move.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# pulse_move.sh [binary name] [sink name] +# +# Use pactl list short sinks to find sink names. +# Will move all streams from a certain binary to the sink. + + +SINK_ID=$(pactl -f json list short sinks | + jq -r ".[] | select(.name == \"$2\") | .index") + +pactl -f json list clients | + jq -r ".[] | select(.properties.\"application.process.binary\" == \"$1\") | .index" | +while read -r clientindex; do + pactl -f json list short sink-inputs | + jq -r ".[] | select(.client == \"$clientindex\") | .index" +done | +while read -r inputindex; do + pacmd move-sink-input $inputindex $SINK_ID +done