Created
April 23, 2020 13:08
-
-
Save kenanpelit/6143a295dd391bcb6bd8454b5aa77875 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby | |
# Filename: pulse-switch-out | |
# Author: David Ljung Madison <DaveSource.com> | |
# See License: http://MarginalHacks.com/License/ | |
# Description: Switch pulse audio output (sink) using pacmd | |
PACMD = %w(pacmd) | |
################################################## | |
# Usage | |
################################################## | |
def fatal(*msg) | |
msg.each { |m| $stderr.puts "[#{$0.sub(/.*\//,'')}] ERROR: #{m}" } | |
exit(-1); | |
end | |
def usage(*msg) | |
msg.each { |m| $stderr.puts "ERROR: #{m}" } | |
$stderr.puts <<-USAGE | |
Usage: #{$0.sub(/.*\//,'')} [sink] | |
Switch sound playback device for ALSA/pulseaudio | |
[sink] Specify sink number to use (see 'pacmd list-sinks') | |
USAGE | |
exit -1; | |
end | |
def parseArgs | |
opt = Hash.new | |
loop { | |
if (arg=ARGV.shift)==nil then break | |
elsif arg == '-h' then usage | |
elsif arg == '-?' then usage | |
#elsif arg == '-arg' then opt[:arg] = true | |
elsif arg =~ /^(\d)$/ then opt[:sink] = arg.to_i | |
else | |
usage("Unknown arg [#{arg}]") | |
end | |
} | |
opt | |
end | |
# Unfortunately you can't return or break from the yield without leaving | |
# the pipe open, maybe use some sort of ensure and figure out how to close? | |
def pipe(cmd) | |
# This is leaving files open | |
#IO.popen(cmd.join(' ')).each { |l| | |
a = `#{cmd.join(' ')}` | |
ret = $? | |
a.split("\n").each { |l| | |
yield l | |
} | |
$? | |
end | |
def getSinks(ins=false) | |
cmd = PACMD.dup | |
cmd.push(ins ? 'list-sink-inputs' : 'list-sinks') | |
curr = nil | |
sinks = Array.new | |
pipe(cmd) { |l| | |
next unless l=~/\s*(\*)?\s*index:\s+(\d+)/ | |
i = $2.to_i | |
sinks.push(i) | |
curr = i if $1 | |
} | |
return sinks,curr | |
end | |
################################################## | |
# Main code | |
################################################## | |
def main | |
opt = parseArgs | |
sinks,curr = getSinks | |
usage("No sinks found?") if sinks.empty? | |
usage("Only one sink found") if sinks.size==1 | |
if opt[:sink] | |
usage("Unknown sink [#{opt[:sink]}] (out of #{sinks.join(' ')})") unless sinks.index(opt[:sink]) | |
else | |
# Find next sink after curr | |
opt[:sink] = sinks[0] | |
sinks.each { |s| | |
next unless s>curr | |
opt[:sink] = s | |
break | |
} | |
end | |
# Set default sink | |
## For some reason this doesn't change the behavior of new apps. | |
puts "Set sink: #{opt[:sink]}" | |
system("#{PACMD.join(' ')} set-default-sink #{opt[:sink]} > /dev/null") | |
usage("Couldn't set default sink [#{opt[:sink]}]") unless $?==0 | |
# And move all sink-inputs to the new sink | |
ins,ignore = getSinks(true) | |
ins.each { |i| | |
puts "Move playback #{i} to sink #{opt[:sink]}" | |
system("#{PACMD.join(' ')} move-sink-input #{i} #{opt[:sink]} > /dev/null") | |
usage("Couldn't move playback #{i} to sink [#{opt[:sink]}]") unless $?==0 | |
} | |
end | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment