raycast / extensions

Everything you need to extend Raycast.
https://developers.raycast.com
MIT License
5.29k stars 2.98k forks source link

[Set Audio Device]... #11131

Open Guolin-Yin opened 7 months ago

Guolin-Yin commented 7 months ago

Extension

https://raycast.com/benvp/audio-device

Description

Error:

Error: Command failed with exit code 1: osascript -e 
    set devices to {}

    tell application "System Preferences"
      reveal pane id "com.apple.preference.sound"
    end tell
    tell application "System Events"
      tell application process "System Preferences"
        repeat until exists tab group 1 of window "Sound"
        end repeat
        tell tab group 1 of window "Sound"
          click radio button "Output"
          tell table 1 of scroll area 1
            set selected_row to (first UI element whose selected is true)
            set currentOutput to value of text field 1 of selected_row as text

            repeat with r in rows
              try
                set deviceName to value of text field 1 of r as text
                set deviceType to value of text field 2 of r as text
                set end of devices to { deviceName, deviceType }
              end try
            end repeat
          end tell
        end tell
      end tell
    end tell

    if application "System Preferences" is running then
      tell application "System Preferences" to quit
    end if

    return [ devices, "currentOutput", currentOutput ]

64:116: execution error: System Settings got an error: Can’t get pane id "com.apple.preference.sound". (-1728)
    at _t (/Users/colinguolin/.config/raycast/extensions/2158713f-4712-4862-ba9a-3bce3cd07e3a/set-output-device.js:5:57)
    at /Users/colinguolin/.config/raycast/extensions/2158713f-4712-4862-ba9a-3bce3cd07e3a/set-output-device.js:5:6400
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async ca (/Users/colinguolin/.config/raycast/extensions/2158713f-4712-4862-ba9a-3bce3cd07e3a/set-output-device.js:41:6806)
    at async b0 (/Users/colinguolin/.config/raycast/extensions/2158713f-4712-4862-ba9a-3bce3cd07e3a/set-output-device.js:41:6981)

Steps To Reproduce

error in "Set Output Device"

Current Behaviour

can fetch the output device in raycast

Expected Behaviour

get the existing output device

raycastbot commented 7 months ago

Thank you for opening this issue!

πŸ”” @benvp @mathieudutour @mike182uk @FezVrasta @rcruzper @thomaspaulmann you might want to have a look.

πŸ’‘ Author and Contributors commands The author and contributors of `benvp/audio-device` can trigger bot actions by commenting: - `@raycastbot close this issue` Closes the issue. - `@raycastbot rename this issue to "Awesome new title"` Renames the issue. - `@raycastbot reopen this issue` Reopen the issue.
iamyeizi commented 7 months ago

I add to the report that this error only happens if you have activated the Airplay option.

CleanShot 2024-03-10 at 8β€― 13 07

Edit: The name of the Sound panel in macOS Ventura has changed to "com.apple.Sound-Settings.extension" and the legacy "com.apple.preference.sound" has been removed.

To start, change that line in src/utils.tsx in the getOutputDevices() and setOutputDevice() functions.

     tell application "System Preferences"
-      reveal pane id "com.apple.preference.sound"
+      reveal pane id "com.apple.Sound-Settings.extension"
     end tell

So it is returning without the pane id number, according to what I have found on the internet it now returns the name.

CleanShot 2024-03-10 at 10β€― 33 36@2x

Now all the getOutputDevices() code keeps failing because it doesn't find that tab group 1 exists, I don't know if it is because it doesn't have the pane id or what is the reason.

CleanShot 2024-03-10 at 10β€― 39 02@2x

raycastbot commented 5 months ago

This issue has been automatically marked as stale because it did not have any recent activity.

It will be closed if no further activity occurs in the next 10 days to keep our backlog clean 😊

raycastbot commented 5 months ago

This issue has been automatically closed due to inactivity.

Feel free to comment in the thread when you're ready to continue working on it πŸ™‚

You can also catch us in Slack if you want to discuss this.

antonengelhardt commented 4 months ago

@iamyeizi

I tried it with Automators "Watch me do" (look here), and then with XCode's Accessibility Inspector (look here) and a lot of ChatGPT/Perplexity.

I am currently stuck with this:

  set devicesList to {} -- Stores output device names
  set currentOutput to "" -- Name of currently used output device

  tell application "System Events"
      tell application "System Settings"
          reveal pane id "com.apple.Sound-Settings.extension" -- Correctly opens the Sound settings pane
          delay 0.5 -- Wait for the pane to display fully, increased delay for slower UI response
      end tell

      tell process "System Settings"
          -- Wait for and click the Output tab using the path obtained from Watch Me Do
          click group 1 of UI element 1 of row 2 of outline 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"
          delay 2 -- Allow time for the output devices list to become visible and interactive

          -- Interact with the outline containing devices
          tell outline 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"
              set numDevices to count rows
              repeat with i from 3 to numDevices - 1
                  set thisDevice to row i
                  set deviceName to value of static text 1 of group 1 of UI element 1 of thisDevice
                  set end of devicesList to deviceName -- Append device name to list
                  -- Identify the currently selected device
                  if selected of thisDevice then
                      set currentOutput to deviceName
                  end if
              end repeat
          end tell
      end tell

      -- Close System Settings after operations are complete
      if application "System Settings" is running then
          tell application "System Settings" to quit
      end if
  end tell

  return {devicesList, "currentOutput", currentOutput}

This snippet is not "done" and ready to be used, just my progress so far.

Nevertheless, the execution of this Apple Script is INCREDIBLY slow (sometimes i takes 4 minutes in the Apple Script editor with 8 devices). I am not sure if there is any other way to manipulate and get the devices... just leaving my thought for now...

And also i think this issue should be reopened, as it contains the most information about the problem (@thomaslombart), #10667 #10934 #12672 are duplicates in that sense...

antonengelhardt commented 4 months ago

This could be interesting. The only downside is the need for a dependency

iamyeizi commented 4 months ago

@antonengelhardt I have no problem with this extension, it works fine for me

antonengelhardt commented 4 months ago

@antonengelhardt I have no problem with this extension, it works fine for me

Also with the AirPlay Setting turned on?

iamyeizi commented 4 months ago

@antonengelhardt I have no problem with this extension, it works fine for me

Also with the AirPlay Setting turned on?

I just tried that, I don't have AirPlay speaker, if you use AirPlay it doesn't work as you mention

antonengelhardt commented 4 months ago

@antonengelhardt I have no problem with this extension, it works fine for me

Also with the AirPlay Setting turned on?

I just tried that, I don't have AirPlay speaker, if you use AirPlay it doesn't work as you mention

Yes, exactly. Actually you brought that up a few months ago. I just had the same problem and found this issue. I'm still trying to fix it...

iamyeizi commented 4 months ago

@antonengelhardt I was able to get an AirPlay enabled device to test.

I also found 2 ways to get this to work, one using Swift with the Bonjour API and the other one using a command that comes in the system. Now I'm going to try to put the swift and applescript outputs together.

Try if you can do something with the output of dns-sd (Multicast DNS (mDNS) & DNS Service Discovery (DNS-SD) Test Tool) and applescript, remember to get the local name of where the extension runs to exclude it from the final list (iCloud name device, isn't the same as the Sharing name, aka "Local hostname"), since your macbook is capable of receiving, it will appear.

Commands: dns-sd -B _raop._tcp or dns-sd -B _airplay._tcp

You can do something like this with applescript: do shell script "dns-sd -B _raop._tcp"

JoeRoddy commented 3 months ago

Issue currently happening for me. With airplay toggled on, trying to connect to my Homepod.

image

If I disable Airplay, I'm able to see my MBP speakers, but that's not particularly helpful.

iamyeizi commented 3 months ago

@JoeRoddy Hey! Yeah, it's because airplay devices are now not accessible from applescript, you need to trigger this with an API. I'm trying to figure it out

raycastbot commented 1 month ago

This issue has been automatically marked as stale because it did not have any recent activity.

It will be closed if no further activity occurs in the next 10 days to keep our backlog clean 😊

antonengelhardt commented 1 month ago

Keep it open

pasteley commented 1 month ago

Patched getOutputDevices from me:

set devices to {}

tell application "System Settings"
    activate -- REQUIRED FOT AIRPLAY DEVICES
    reveal pane id "com.apple.Sound-Settings.extension"
end tell

tell application "System Events" to tell application process "System Settings"
    repeat until exists window "Sound"
    end repeat
    tell group 2 of scroll area 1 of group 1 of group 2 of splitter group 1 of group 1 of window "Sound"
        click radio button 1 of tab group 1

        tell outline 1 of scroll area 1
            set selected_row to (first UI element whose selected is true)
            set currentOutput to value of static text of group 1 of UI element 1 of selected_row as text

            repeat with r in rows
                try
                    set deviceName to value of static text of group 1 of UI element 1 of r as text
                    set deviceType to value of static text of group 1 of UI element 2 of r as text
                    set end of devices to {deviceName, deviceType}
                end try
            end repeat
        end tell
    end tell
end tell

tell application "System Settings" to quit
return [devices, "currentOutput", currentOutput]

This one works even without delay for me but System Settings app pop ups by this way. Probably can be avoided by changing focused app back to Raycast. There is another way to implement it using ControlCenter:

set deviceNames to {}

tell application "System Events"
    tell its application process "ControlCenter"
        set soundMenu to menu bar item 5 of menu bar 1
        click soundMenu
        delay 0.5 -- WAIT FOR AIRPAY DEVICES TO SHOW UP
        tell window 1
            tell its group 1                
                set deviceElements to checkboxes of scroll area 1
                repeat with deviceElement in deviceElements
                    set deviceMenuName to value of attribute "AXIdentifier" of deviceElement
                    set deviceName to text 14 thru -1 of deviceMenuName -- TRIM 'sound-device-' PREFIX
                    if value of attribute "AXValue" of deviceElement as boolean is true then
                        set currentOutput to deviceName
                    end if
                    set end of deviceNames to deviceName
                end repeat
            end tell
        end tell
        click soundMenu
    end tell
end tell

return [deviceNames, "currentOutput", currentOutput] -- WITHOUT TYPE OF DEVICE (BUILT-IN, BT, AIRPLAY)

But all of those solutions looks horrible, it would be much better to support it directly via coreaudio lib here: https://github.com/karaggeorge/macos-audio-devices/issues/22 Or this way: https://github.com/raycast/extensions/pull/3613#issuecomment-1356881672

iamyeizi commented 1 month ago

Hi! @pasteley πŸ‘‹πŸ½ None of these solutions work for me at my local, how did u implement it?

raycastbot commented 7 hours ago

This issue has been automatically marked as stale because it did not have any recent activity.

It will be closed if no further activity occurs in the next 10 days to keep our backlog clean 😊