deweller / switchaudio-osx

Change the audio source for Mac OS X from the command line.
Other
1.19k stars 88 forks source link

unable to switch to AirPlay output 'devices' #9

Open arkarkark opened 8 years ago

arkarkark commented 8 years ago

I'm unable to switch to my airplay 'speakers'

image

$ SwitchAudioSource -a
Built-in Microphone (input)
Built-in Output (output)
$ SwitchAudioSource -t output  -s "Garage"
Could not find an audio device named "Garage" of type output.  Nothing was changed.
crcastle commented 1 year ago

If someone finds a way to tweak this, so it works hidden (or at least in the background), please post your solution.

I didn't find a way to do this in the background, but you can replace the delay with a loop waiting until the Sound window exists.

Here is the diff

--- a/a.scpt
+++ b/b.scpt
@@ -5,10 +5,11 @@ tell application "System Settings"
    reveal anchor "output" of pane id "com.apple.Sound-Settings.extension"
 end tell

-delay 2
-
 tell application "System Events"
    tell application process "System Settings"
+       -- Wait until Sound window is available to interact with
+       repeat until exists window "Sound"
+       end repeat
+
        set theRows to (every row of table 1 of scroll area 1 of group 2 of scroll area 1 of group 1 of group 2 of splitter group 1 of group 1 of window "Sound")
        repeat with myDevice in myDevices
            set theDevice to myDevice as string

And here is the full updated script.

set myDevices to {"HomePod"}

tell application "System Settings"
    activate
    reveal anchor "output" of pane id "com.apple.Sound-Settings.extension"
end tell

tell application "System Events"
    tell application process "System Settings"
        -- Wait until Sound window is available to interact with
        repeat until exists window "Sound"
        end repeat

        set theRows to (every row of table 1 of scroll area 1 of group 2 of scroll area 1 of group 1 of group 2 of splitter group 1 of group 1 of window "Sound")
        repeat with myDevice in myDevices
            set theDevice to myDevice as string
            repeat with aRow in theRows
                if name of first item of static text of group 1 of UI element 1 of aRow is equal to theDevice then
                    set selected of aRow to true
                    exit repeat
                end if
            end repeat
        end repeat
    end tell
end tell

quit application "System Settings"
jdsimcoe commented 1 year ago

Oh nice! This is great!

JayBrown commented 1 year ago

Thank you! 👍 fyi, also for @deweller: @alanhg has forked this repo and is working on a solution to include AirPlay support. See here: https://github.com/alanhg/switchaudio-osx 🤞

davidaberg commented 1 year ago

Update for for Sonoma RC

set myDevices to {"HomePod"}

tell application "System Settings"
    activate
    delay 1
    reveal anchor "output" of pane id "com.apple.Sound-Settings.extension"
end tell

tell application "System Events"
    tell application process "System Settings"
        repeat until exists window "Sound"
        end repeat
        delay 1
        set theRows to (every row of outline 1 of scroll area 1 of group 2 of scroll area 1 of group 1 of list 2 of splitter group 1 of list 1 of window "Sound")
        repeat with myDevice in myDevices
            set theDevice to myDevice as string
            repeat with aRow in theRows
                if name of first item of static text of group 1 of UI element 1 of aRow is equal to theDevice then
                    set selected of aRow to true
                    exit repeat
                end if
            end repeat
        end repeat
    end tell
end tell
quit application "System Settings"

I used an app called UI Builder to fetch the UI path. Warm recommendation.

hjoelh commented 1 year ago

Following this stackoverflow answer & script

I got this slightly modified version to work on my m2 macbook

airplay.applescript (you probably just need to update property airPlayDevice : "Bedroom"

property airPlayDevice : "Bedroom"
property localDevice : "MacBook Pro Speakers"

global initialApplication, initialWindow, currentAudioSource, availableAudioSources

set the currentAudioSource to (do shell script "/opt/homebrew/bin/SwitchAudioSource -c")
set the availableAudioSources to paragraphs of (do shell script "/opt/homebrew/bin/SwitchAudioSource -a")

if currentAudioSource is equal to localDevice then
    if availableAudioSources contains "Airplay" then
        switchToDevice("Airplay")
    else
        connectToAirPlayDevice()
    end if
else
    switchToDevice(localDevice)
end if

-- Switch the current device using switchaudio-osx.
on switchToDevice(device)
    do shell script "/opt/homebrew/bin/SwitchAudioSource -s " & quoted form of device
end switchToDevice

-- Connect to the desired AirPlay device.
on connectToAirPlayDevice()
    openAudioDevices()
    tell application "System Events" to tell application process "Audio MIDI Setup"
        click menu button 1 of splitter group 1 of window "Audio Devices"
        click menu item "Connect AirPlay Device" of menu 1 of menu button 1 of splitter group 1 of window "Audio Devices"
        set the availableDevice to "No AirPlay devices available"
        repeat while availableDevice is "No AirPlay devices available"
            set availableDevice to name of first menu item of menu 1 of menu item "Connect AirPlay Device" of menu 1 of menu button 1 of splitter group 1 of window "Audio Devices"
        end repeat
        click (menu item airPlayDevice of menu 1 of menu item "Connect AirPlay Device" of menu 1 of menu button 1 of splitter group 1 of window "Audio Devices")
    end tell
    tell application "Audio MIDI Setup" to quit
end connectToAirPlayDevice

-- Open and focus Audio Devices
on openAudioDevices()
    tell application "Audio MIDI Setup"
        reopen
        activate
    end tell
    tell application "System Events"
        repeat until (exists window "Audio Devices" of application process "Audio MIDI Setup")
            delay 0.01
        end repeat
    end tell
end openAudioDevices

You can run this like so

osascript airplay.applescript
chengrutw commented 1 year ago

Update for for Sonoma RC

set myDevices to {"HomePod"}

tell application "System Settings"
  activate
  delay 1
  reveal anchor "output" of pane id "com.apple.Sound-Settings.extension"
end tell

tell application "System Events"
  tell application process "System Settings"
      repeat until exists window "Sound"
      end repeat
      delay 1
      set theRows to (every row of outline 1 of scroll area 1 of group 2 of scroll area 1 of group 1 of list 2 of splitter group 1 of list 1 of window "Sound")
      repeat with myDevice in myDevices
          set theDevice to myDevice as string
          repeat with aRow in theRows
              if name of first item of static text of group 1 of UI element 1 of aRow is equal to theDevice then
                  set selected of aRow to true
                  exit repeat
              end if
          end repeat
      end repeat
  end tell
end tell
quit application "System Settings"

I used an app called UI Builder to fetch the UI path. Warm recommendation.

Hi @davidaberg,

This is no longer working in Sonoma. Could you help to fix it? Thanks!

lotech commented 4 months ago

+1 to a fix but I have fixed the code from hjoelh.

Fixed the default install location of SwitchAudioSource (/opt/homebrew/opt/switchaudio-osx/SwitchAudioSource) and added a 1 second delay on the showing the Airplay devices on Audio MIDI Setup - mine would show nothing if the script ran too quickly.

Not sure why Github won't display the code in a nice copyable window right now but here it is -

` property airPlayDevice : "ERA 300" property localDevice : "Mac Studio Speakers"

global initialApplication, initialWindow, currentAudioSource, availableAudioSources

set the currentAudioSource to (do shell script "/opt/homebrew/opt/switchaudio-osx/SwitchAudioSource -c") set the availableAudioSources to paragraphs of (do shell script "/opt/homebrew/opt/switchaudio-osx/SwitchAudioSource -a")

if currentAudioSource is equal to localDevice then if availableAudioSources contains "Airplay" then switchToDevice("Airplay") else connectToAirPlayDevice() end if else switchToDevice(localDevice) end if

-- Switch the current device using switchaudio-osx. on switchToDevice(device) do shell script "/opt/homebrew/opt/switchaudio-osx/SwitchAudioSource -s " & quoted form of device end switchToDevice

-- Connect to the desired AirPlay device. on connectToAirPlayDevice() openAudioDevices() tell application "System Events" to tell application process "Audio MIDI Setup" delay 1 click menu button 1 of splitter group 1 of window "Audio Devices" click menu item "Connect AirPlay Device" of menu 1 of menu button 1 of splitter group 1 of window "Audio Devices" delay 1 set the availableDevice to "No AirPlay devices available" repeat while availableDevice is "No AirPlay devices available" set availableDevice to name of first menu item of menu 1 of menu item "Connect AirPlay Device" of menu 1 of menu button 1 of splitter group 1 of window "Audio Devices" end repeat click (menu item airPlayDevice of menu 1 of menu item "Connect AirPlay Device" of menu 1 of menu button 1 of splitter group 1 of window "Audio Devices") end tell tell application "Audio MIDI Setup" to quit end connectToAirPlayDevice

-- Open and focus Audio Devices on openAudioDevices() tell application "Audio MIDI Setup" reopen activate end tell tell application "System Events" repeat until (exists window "Audio Devices" of application process "Audio MIDI Setup") delay 0.01 end repeat end tell end openAudioDevices `

lotech commented 4 months ago

Actually the fix seems to only work half the time - I think theres a bug in Audio MIDI Setup which seems to screw up the listing on Airplay devices every time.