Created
September 11, 2020 10:18
-
-
Save ttscoff/c5d61971d5251b8795af2415cc1bbb85 to your computer and use it in GitHub Desktop.
Script for macOS to save and restore audio input/output device and volume settings
This file contains hidden or 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/env ruby | |
# frozen_string_literal: true | |
# Brett Terpstra <https://brettterpstra.com> | |
# | |
# macOS: Stores all input/output devices and volume settings to a | |
# text file, restores on demand | |
# | |
## Dependencies | |
# SwitchAudioSource <https://github.com/deweller/switchaudio-osx> | |
# Install with Homebrew: `brew install switchaudio-osx` | |
# | |
## Usage: | |
# volumetoggle.rb save | |
# volumetoggle.rb restore | |
require 'yaml' | |
TYPE_OUTPUT = 'output' | |
TYPE_INPUT = 'input' | |
TYPE_SYSTEM = 'system' | |
STORE_FILE = File.expand_path('~/.saved_volume') | |
SWITCH_AUDIO = '/usr/local/bin/SwitchAudioSource' | |
def get_device(type) | |
`#{SWITCH_AUDIO} -c -t #{type}`.strip | |
end | |
def set_device(type, device) | |
`#{SWITCH_AUDIO} -t #{type} -s "#{device}"` | |
end | |
def set_volume(type, volume, muted = nil) | |
script = "set volume #{type} volume #{volume}" | |
if type == TYPE_OUTPUT | |
script += " #{(muted ? ' with' : ' without')} output muted" | |
end | |
`osascript -e "#{script}"` | |
end | |
# String helpers | |
class String | |
def to_literal | |
case self | |
when /\d+/ | |
to_i | |
when /true/ | |
true | |
when /false/ | |
false | |
when /missing value/ | |
nil | |
end | |
end | |
def to_literal! | |
replace to_literal | |
end | |
def to_h | |
output = {} | |
split(/, /).each do |item| | |
parts = item.split(/:/)[0..1] | |
k = parts[0] =~ /muted/ ? 'muted' : parts[0].sub(/ volume/, '') | |
k = k.to_sym | |
v = parts[1].to_literal | |
output[k] = v | |
end | |
output | |
end | |
end | |
case ARGV[0] | |
when /save/ | |
devices = {} | |
devices[:input] = get_device(TYPE_INPUT) | |
devices[:output] = get_device(TYPE_OUTPUT) | |
devices[:system] = get_device(TYPE_SYSTEM) | |
settings = `osascript -e 'return (get volume settings)'`.strip.to_h | |
settings[:devices] = devices | |
File.open(STORE_FILE, 'w') do |f| | |
f.puts YAML.dump(settings) | |
end | |
warn "Settings written to #{STORE_FILE}" | |
when /restore/ | |
raise "No store file found at #{STORE_FILE}" unless File.exist?(STORE_FILE) | |
settings = YAML.load(IO.read(STORE_FILE)) | |
settings[:devices].each { |k, v| set_device(k.to_s, v) } | |
%i[output input alert].each do |sym| | |
set_volume(sym.to_s, settings[sym], settings[:muted]) if settings[sym] | |
end | |
warn 'Settings restored' | |
warn YAML.dump settings | |
else | |
warn 'Requires argument' | |
warn "#{File.basename(__FILE__)} save or #{File.basename(__FILE__)} save" | |
Process.exit 1 | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment