Audio input/output device selector

Hi All,

I wrote this to speed the process of changing the input/output/system devices. Allows you to change one or more devices simultaneously. See the first few comments for links to the CLI tools required.

Edit: And don’t forget to set the top two properties to reflect the locations of the CLI tools.

Tim

property AudioSwitcher : "/usr/local/bin/AudioSwitcher "
property AudioDevice : "/usr/local/bin/audiodevice "

--audioswitcher (https://github.com/deweller/switchaudio-osx) and audiodevice (http://whoshacks.blogspot.com/2009/01/change-audio-devices-via-shell-script.html) will give different names to certain audio devices, where the device names according to audiodevice will matching with those you see in the volume menu (option-click the volume menu bar item). If you see something that doesn't match up, then use the below property to make a relationship.
--use ReplaceWords to change from the audiodevice name (left) to the audioswitcher name (right)
property ReplaceWords : {{"Internal Speakers", "Built-in Output"}, {"Internal Microphone", "Built-in Microphone"}, {"BenQ GW2765", "HDMI"}, {"Kuro", "AirPlay"}}
--These are the prefixes that come with the output of audiodevice, so this is to replace them with a blank string
property BlankWords : {"input: ", "output: ", "system: "}

on run
	local InputList, OutputList, FullList
	local ChooseList, CurrentList
	local InSelected, OutSelected, SysSelected
	
	set InputList to {"” INPUT ”"}
	set OutputList to {"” OUTPUT ”"}
	set SystemList to {"” SYSTEM ”"}
	set ChooseList to {}
	
	set FullList to paragraphs of (do shell script AudioSwitcher & "-a")
	set CurrentList to paragraphs of (do shell script AudioDevice)
	if (count of CurrentList) < 1 then
		repeat with i in OutputList
			if (i contains "Built") then
				set CurrentList to {i}
				exit repeat
			end if
		end repeat
	end if
	
	
	
	repeat with i from 1 to count of CurrentList
		set (item i of CurrentList) to replaceString(item i of CurrentList, item i of BlankWords, "")
		repeat with j in ReplaceWords
			if (item i of CurrentList as string) contains ((beginning of j) as string) then
				set (item i of CurrentList) to (end of j)
				exit repeat
			end if
		end repeat
	end repeat
	
	repeat with i in FullList
		if i contains " (input)" then
			set end of InputList to i
			considering case
				if (i as string) contains ((item 1 of CurrentList) as string) then
					set (item 1 of CurrentList) to ("In:: " & (item 1 of CurrentList) & " (input)") as string
				end if
			end considering
		else if i contains " (output)" then
			set end of OutputList to i
			set end of SystemList to i
			considering case
				if (i as string) contains ((item 2 of CurrentList) as string) then
					set (item 2 of CurrentList) to ("Out:: " & (item 2 of CurrentList) & " (output)") as string
				end if
				if (i as string) contains ((item 3 of CurrentList) as string) then
					set (item 3 of CurrentList) to ("Sys:: " & (item 3 of CurrentList) & " (output)") as string
				end if
			end considering
		end if
	end repeat
	
	repeat with i in OutputList
		if FullList contains i then
			set end of ChooseList to "Out:: " & i
		else
			set end of ChooseList to i
		end if
	end repeat
	repeat with i in InputList
		if FullList contains i then
			set end of ChooseList to "In:: " & i
		else
			set end of ChooseList to i
		end if
	end repeat
	repeat with i in SystemList
		if FullList contains i then
			set end of ChooseList to "Sys:: " & i
		else
			set end of ChooseList to i
		end if
	end repeat
	
	tell me to activate
	set ChooseList to choose from list ChooseList with prompt "(Current devices are selected)" with title "Select input/output device(s)" default items CurrentList with multiple selections allowed without empty selection allowed
	if ChooseList is false then return
	
	set InSelected to false
	set OutSelected to false
	set SysSelected to false
	
	repeat with i in ChooseList
		if i contains "Out:: " then
			set OutSelected to true
			set OutputList to quoted form of beginning of ParseLine(end of ParseLine(i, "Out:: "), " (output)")
		else if i contains "In:: " then
			set InSelected to true
			set InputList to quoted form of beginning of ParseLine(end of ParseLine(i, "In:: "), " (input)")
		else if i contains "Sys:: " then
			set SysSelected to true
			set SystemList to quoted form of beginning of ParseLine(end of ParseLine(i, "Sys:: "), " (output)")
		end if
	end repeat
	
	if OutSelected then
		do shell script AudioSwitcher & "-t output -s " & OutputList
	end if
	if InSelected then
		do shell script AudioSwitcher & "-t input -s " & InputList
	end if
	if SysSelected then
		do shell script AudioSwitcher & "-t system -s " & SystemList
	end if
end run

--c--   replaceString(theText, oldString, newString)
--d--   Case-sensitive find and replace of all occurrences.
--a--   theText : string -- the string to search
--a--   oldString : string -- the find string
--a--   newString : string -- the replacement string
--r--   string
--x--   replaceString("Hello hello", "hello", "Bye") --> "Hello Bye"
--u--   ljr (http://applescript.bratis-lover.net/library/string/)
on replaceString(theText, oldString, newString)
	local astid, theText, oldString, newString, lst
	set astid to AppleScript's text item delimiters
	try
		considering case
			set AppleScript's text item delimiters to oldString
			set lst to every text item of theText
			set AppleScript's text item delimiters to newString
			set theText to lst as string
		end considering
		set AppleScript's text item delimiters to astid
		return theText
	on error eMsg number eNum
		set AppleScript's text item delimiters to astid
		error "Can't replaceString: " & eMsg number eNum
	end try
end replaceString

on ParseLine(theLine, delimiter)
	-- This came from Nigel Garvey
	
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to {delimiter}
	set theTextItems to theLine's text items
	set AppleScript's text item delimiters to astid
	
	set outText to {}
	
	repeat with i from 1 to (count theTextItems)
		if (item i of theTextItems is not "") then set end of outText to item i of theTextItems
	end repeat
	
	return outText
end ParseLine