How do i check if there is an Airplay device connected - macos

I'm wanting to do a script that needs to check if there is an airplay device connected and being used.
I have tried searching in many places but i can't seem to find any documentation on this, does anyone have any idea how i would do this?
To further clarify, I want a script that is something along the lines of:
if airplay device is in use then //(pause for longer)
else //(the script that is already there)
this is the current code i have
global okflag
set okflag to false
set front_app to (path to frontmost application as Unicode text)
-- check if iTunes is running
tell application "System Events"
if process "iTunes" exists then
set okflag to true --iTunes is running
end if
end tell
if okflag is true then
set CV to output volume of (get volume settings)
tell application "iTunes"
if (player state is playing) then
set currentVolume to the sound volume
set Timer to ""
display dialog "Sleep Time (Minutes)" with title "iTunes Timer" default answer Timer buttons {"Cancel", "OK"} default button 2
set Timer to text returned of the result
set the_button to button returned of (display dialog "Shutdown after countdown?" with title "iTunes Timer" buttons {"No", "Yes"} default button 2)
delay Timer * 60
repeat with i from currentVolume to 0 by -1
set the sound volume to i
delay 0.6
end repeat
pause
set player position to (player position - 60)
--Restore original volume
set the sound volume to currentVolume
if the_button is "Yes" then tell application "System Events"
shut down
end tell
else
display dialog "Nothing Playing" with title "iTunes Timer" giving up after 2
end if
end tell
else
display dialog "iTunes is not running" with title "iTunes Timer" giving up after 2
end if
edit: added application for clarification of what i needed to find out

Hmm.
But did not workout how to get a status if you are streaming say from iTunes. (so far)
But did workout that if airplay is being used as a Extended desktop space or Mirroring then That is picked up in the System Profile for displays. SPDisplaysDataType
This applescript accounts for that at least.
set connected to ""
try
set connected to do shell script "system_profiler SPDisplaysDataType | grep -i \"AirPlay\" "
if connected contains "Connection Type: AirPlay" then
set connected to "Connected as a Display or mirroring"
end if
on error err
log err
if err contains "The command exited with a non-zero status" then
--do somthing
set connected to "Not connected as a Display or mirroring"
end if
end try
connected
UPDATE*
The iTunes commands now have some airplay commands. Not sure when they appeared.
But one example of use:
tell application "iTunes"
set isPlaying to player state
if isPlaying is playing then
log isPlaying
set airPlayEnabled to AirPlay enabled
if airPlayEnabled then
log airPlayEnabled
else
airPlayEnabled
end if
else
log isPlaying
end if
end tell
The AirPlay enabled AFAIK only for the iTunes player it is run against. And not for any other device that may be occupying the Airplay device

Related

How to programmatically change audio output to built in Mac speakers ALWAYS [Shell]

So I've seen answers like these but what I'm trying to do is programmatically ALWAYS set the audio output to built-in speakers regardless of which row item the Mac is currently tuned to.
In the below code (cited from the above link), the user selects between items 3 and 4. We know that built in speakers are always item 1, so is there a simpler way to achieve this where you send a shell command to always set the audio output to Built-in speakers?
(*
Applescript to toggle between two sound outputs by Line number, ¬
as they appear in the Sound Control Panel. Based on code by ¬
Arthur Hammer http://apple.stackexchange.com/a/209434/85275
*)
set internal to 1 --internal speakers
set appletv to 3 --Follows internal speakers and separator line for Airplay devices
tell application "System Preferences"
activate
set current pane to pane "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"
if (selected of row internal of table 1 of scroll area 1) then
set selected of row appletv of table 1 of scroll area 1 to true
else
set selected of row internal of table 1 of scroll area 1 to true
end if
end tell
end tell
end tell
tell application "System Preferences" to quit

Applescript moving finder window or screen back to first screen

I am writing a script and want to hem in the user(s) in the future from errors. The big one I'm working on right now is that the Choose File command box for Finder or AppleScript (doesn't matter) do not contain the "giving up after" option. So while I can set the timeout to a very large number of seconds (5000 for example), I can't get the box to close and reopen without the Apple Events timing out.
So here is one option I've tried. but the problem I have is that if I swipe to another screen, even if I Activate the finder, it will say that it can't find the window "Choose a File"
Is there a way to get the window to follow the swipe or a command with activate that will bring the finder window to the current screen, even if I'm working in say Safari?
The error occurs when I swipe to another screen; see the error below:
error "System Events got an error: Can’t get window \"Choose a File\" of process \"Finder\"." number -1728 from window "Choose a File" of process "Finder"
Script:
try
with timeout of 5 seconds
tell application "Finder"
set theFilestoChoose to every item of (choose file with prompt "Please select the file(s) you would like to move and rename:" with multiple selections allowed) as list
end tell
end timeout
on error errStr number errorNumber
if errorNumber is -1712 then --timeout error
my closeWindow() --call handler to close window
end if
end try
on closeWindow()
tell application "System Events"
delay 2 -- for observation testing purposes
set frontmost of process "Finder" to true
delay 2 -- for observation testing purposes
click button "Cancel" of window "Choose a File" of process "Finder"
end tell
end closeWindow
You'll have to look into the defaults setting AutoSwoosh = true; defaults write com.apple.Dock workspaces-auto-swoosh -bool YES ; KillAll Dock which makes you go to the active app, if it isn't in the current space, the app itself, (Finder in this case?), shouldn't be assigned to a space.
If that is your basic configuration, then a simple activate before it, should bring you directly to your choose file dialog, if it is in another space.
Here is a fleshed out example of embedding the choose file with tell application (path to frontmost application as text):
tell application (path to frontmost application as text)
set theF to (choose file)
end tell

Listing all windows of all applications

I am trying to write an applescript script that resizes all open windows. In order to make sure that I'm getting to all the windows, I'm making my script say the name of the application as well as the number of open windows of that application.
Interestingly, while I hear the names of all my open applications, my script says that they all have 0 windows open. How can I fix this issue?
Here's my code:
tell application "System Events"
repeat with theProcess in (every process)
if background only of theProcess is false then
if name of theProcess is not "Finder" then
if name of theProcess is "Google Chrome" then
say "Chrome woo hoo"
say (count windows as string)
else
say name of theProcess as string
say (count windows as string)
tell theProcess
repeat with theWindow in windows
say "found a window of"
say (name of theProcess) as string
tell theWindow
click button 2
end tell
end repeat
end tell
end if
end if
end if
end repeat
end tell
I'm on Mac OS X 10.7.5, using automator 2.2.4 to write/run this applescript
You have to tell the process to count windows. After all it's the process that knows about its windows, not system events.
You have told the process to say its name e.g. "say name of theProcess as string" however you only use "say (count windows as string)"... no process is tied to that. Try "count windows of theProcess". Basically you have lines where sometimes you tell the process, other times you don't, and other times where you tell the process even though you've already told the process, so you do it twice. That's where you have "say (name of theProcess) as string" but that code is inside a "tell theProcess" block so it's already being told to theProcess.
Really you need to go through your code and be more precise. A tip... if you want to click a button in a window then the window must be frontmost on the screen otherwise you can't click it. Another tip... "name" is already a string so you don't need to coerce that to a string.
By the way, I agree with Michael Dautermann's comment to your post... there will be processes where you won't get access. But you'll find that out as you progress.
Here's how I would write your code. Basically I would get all of the variables at the beginning using a "tell theProcess" block. Then I can do stuff with those variables. I hope that helps. Notice that I only made the process frontmost which means if it has multiple windows open it will only click a button on the front window. You'll have to add code to make each window come to the front before you can click its button. Good luck.
tell application "System Events"
repeat with theProcess in processes
if not background only of theProcess then
tell theProcess
set processName to name
set theWindows to windows
end tell
set windowsCount to count of theWindows
if processName is "Google Chrome" then
say "Chrome woo hoo"
say windowsCount as text
else if processName is not "Finder" then
say processName
say windowsCount as text
if windowsCount is greater than 0 then
repeat with theWindow in theWindows
say "found a window of " & processName
tell theProcess
set frontmost to true
tell theWindow
click button 2
end tell
end tell
end repeat
end if
end if
end if
end repeat
end tell
I create a list of all open windows of visible applications on Mavericks like this:
tell application "System Events"
set this_info to {}
repeat with theProcess in (application processes where visible is true)
set this_info to this_info & (value of (first attribute whose name is "AXWindows") of theProcess)
end repeat
this_info -- display list in results window of AppleScript Editor
end tell
You need to allow any app using this to access the interface under Accessibility.

Spotify's "player state" is available in the editor, but in a packaged app, it gets only "«constant ****kPSP»"

Here's a testing code:
tell application "Spotify"
set playerState to player state as string
end tell
display dialog playerState
Works fine from the AppleScript editor. However, when I export my script as an app, all I get is this:
Why is this happening?
It seems that Spotify is not coercing the constant into a string. Since the editor can't coerce it from an applet as it does when you are running the script in AppleScript Editor, the four-letter constant code is returned. Since you can't test the player state's value as a string, try to test it against the constants themselves.
property spotPause : «constant ****kPSp»
property spotPlay : «constant ****kPSP»
tell application "Spotify" to set playerState to player state
if playerState = spotPause then
display dialog "paused"
else if playerState = spotPlay then
display dialog "playing"
end if
It's better to use this code to obtain the player state. You don't need to know the exact constant values. Works on OS X 10.13
tell application "Spotify"
if player state is playing then
display dialog "Player running"
else if player state is paused then
display dialog "Player paused"
else if player is stopped then
display dialog "Player is stopped"
else
display dialog "Unknow state"
end if
end tell
I wasn't able to comment adayzdone's answer yet here's an alternative:
if player state is playing or player state is paused then
E.G
if application "Spotify" is running then
tell application "Spotify"
if player state is playing or player state is paused then
set trackID to (get id of current track)
end if
end tell
end if
This atleast worked on Catalina (10.15.7) when working on a Spotify-Applescript project of my own.
The source of the idea came from this thread.

AppleScript: Use Lion Fullscreen

There doesn't seem to be any information on this in the official Apple documentation. How do you make an application use Lion's new fullscreen feature via AppleScript?
Not only is it not documented, but the behavior is downright byzantine.
The following applies to Mountain Lion (as of 10.8.1), but I suspect it applies to Lion equally.
The short of it:
You can only examine a fullscreen window's state if it is the active window of the frontmost application. Thus, you must first activate any window you want to examine.
If that window is indeed currently in fullscreen mode but not the active one, activating will take some time - the duration of the transition animation - only after which the window is accessible programmatically.
As long as you're only interested in the active (front) window of the active (frontmost) application, everything's dandy; you're in for pain otherwise.
Below are scripts that do the following:
Indicate if the active window in the active (frontmost) application is in fullscreen mode.
Toggle fullscreen status of the active window in the active application.
Indicate if a specifiable application has any fullscreen windows.
A general-purpose fullscreen-management script that can target a specifiable application; this is much more complex than it should have to be.
Finally, there's some additional background information at the end - great fun.
Note that the scripts below require access for assistive devices to be enabled via System Preferences > Accessibility, or via the following command: tell application "System Events" to set UI elements enabled to true; administrative privileges are required.
Indicates if the active window in the active (frontmost) application is in fullscreen mode
(*
Indicates if the active window of the active application is currently in fullscreen mode.
Fails silently in case of error and returns false.
*)
on isFullScreen()
tell application "System Events"
try
tell front window of (first process whose frontmost is true)
return get value of attribute "AXFullScreen"
end tell
end try
end tell
return false
end isFullScreen
Toggles fullscreen status of the active window in the active application
(*
Toggles fullscreen status of the active window of the active application.
Return value indicates if the window is in fullscreen mode *after* toggling.
Fails silently in case of error, e.g., if the active application doesn't support fullscreen mode, and returns false.
*)
on toggleFullScreen()
set isFullScreenAfter to false
tell application "System Events"
try
tell front window of (first process whose frontmost is true)
set isFullScreen to get value of attribute "AXFullScreen"
set isFullScreenAfter to not isFullScreen
set value of attribute "AXFullScreen" to isFullScreenAfter
end tell
end try
end tell
return isFullScreenAfter
end toggleFullScreen
Indicates if a specifiable application has any fullscreen windows
** Note: This subroutine will only work with AppleScript-enabled applications.**
(*
Determine if the specified, *AppleScript-enabled* application currently has windows in fullscreen mode or not.
Note: Assumes that the application name is the same as the process name.
*)
on hasFullScreenWindows(appName)
-- We compare the count of visible application windows to the count of the application *process'* windows.
-- Since process windows either do not include the fullscreen windows or, if a fullscreen window
-- is active, only report that one window, a discrepancy tells us that there must be at least one fullscreen window.
set countAllWindows to count (windows of application appName whose visible is true)
tell application "System Events" to set countProcessWindows to count windows of process appName
if countAllWindows is not countProcessWindows then
set hasAny to true
else
set hasAny to false
-- The app-window count equals the process-window count.
-- We must investigate one additional case: the app may be currently frontmost and could have
-- a single window that is in fullscreen mode.
tell application "System Events"
set activeProcName to name of first process whose frontmost is true
if activeProcName is appName then
tell process appName
tell front window
set hasAny to get value of attribute "AXFullScreen"
end tell
end tell
end if
end tell
end if
return hasAny
end hasFullScreenWindows
General-purpose fullscreen-management script that can target a specifiable application
** Note: This subroutine will only work with AppleScript-enabled applications.**
(*
Sets the fullscreen status for either the front window or all windows of the specified, *AppleScript-enabled* application.
The 2nd parameter can take the following values:
0 … turn fullscreen OFF
1 … turn fullscreen ON
2 … toggle fullscreen
The 3rd parameter is used to specify whether *all* windows should be targeted.
Example:
my setFullScreen("Safari", 2, false) toggles fullscreen status of Safari's front window.
NOTE:
- ONLY works with AppleScript-enabled applications.
- The targeted application is also activated (also required for technical reasons).
- If you target *all* windows of an application, this subroutine will activate them one by one, which
is required for technical reasons, unfortunately.
This means: Whenever you target *all* windows, expect a lot of visual activity, even when
the fullscreen status needs no changing; activity is prolonged when fullscreen transitions
are involved.
- If the target application has a mix of fullscreen and non-fullscreen windows and the application
is not currently frontmost, the OS considers the first *non*-fullscreen window to
be the front one, even if a fullscreen window was active when the application was
last frontmost.
*)
on setFullScreen(appName, zeroForOffOneForOnTwoForToggle, allWindows)
# Get window list and count.
tell application appName
set wapp_list to windows whose visible is true
set wcount to count of wapp_list
## set wapp_names to name of windows whose visible is true
## log wapp_names
end tell
set MAX_TRIES to 20 # Max. number of attempts to obtain the relevant process window.
set toggle to zeroForOffOneForOnTwoForToggle is 2
set turnOn to false
if not toggle then set turnOn to zeroForOffOneForOnTwoForToggle is 1
if allWindows and wcount > 1 then -- Target *all* the application's windows.
tell application "System Events"
tell process appName
set indexOfTrueFrontWin to -1
set wproc_target to missing value
set wproc_targetName to missing value
-- Loop over application windows:
-- Note that we have 2 extra iterations:
-- Index 0 to determine the index of the true front window, and count + 1 to process the true front window last.
repeat with i from 0 to wcount + 1
## log "iteration " & i
if i ≠ 0 and i = indexOfTrueFrontWin then
## log "ignoring true front win for now: " & i
else
set ok to false
if i ≠ 0 then
set wapp_index to i
if i = wcount + 1 then set wapp_index to indexOfTrueFrontWin
set wapp_target to get item wapp_index of wapp_list
set wapp_targetName to get name of wapp_target -- Note: We get the name up front, as accessing the property below sometimes fails.
end if
repeat with attempt from 1 to MAX_TRIES
## log "looking for #" & i & ": [" & wapp_targetName & "] (" & id of wapp_target & ")"
# NOTE: We MUST activate the application and the specific window in case that window is in fullscreen mode.
# Bizzarrely, without activating both, we would not gain access to that active window's *process* window,
# which we need to examine and change fullscreen status.
if i ≠ 0 then
## log "making front window: " & wapp_targetName
set index of wapp_target to 1 -- Make the window the front (active) one; we try this *repeatedly*, as it can get ignored if a switch from a previous window hasn't completed yet.
end if
set frontmost to true -- Activate the application; we also do this repeatedly in the interest of robustness.
delay 0.2 -- Note: Only when the window at hand is currently in fullscreen mode are several iterations needed - presumably, because switching to that window's space takes time.
try
-- Obtain the same window as a *process* window.
-- Note: This can fail before switching to a fullscreen window is complete.
set wproc_current to front window
-- See if the desired process window is now active.
-- Note that at this point a previous, fullscreen window may still be reported as the active one, so we must
-- test whether the process window just obtained it is the desired one.
-- We test by *name* (window title), as that is the only property that the *application*
-- window class and the *process* window class (directly) share; sadly, only application windows
-- have an 'id' property.
-- (There is potential for making this more robust, though, by also comparing window sizes.)
if i = 0 then
-- We determine the index of the *actual* front window, so we can process it *last*
-- so we return to the same window that was originally active; with fullscreen windows
-- involved, sadly, `front window` is NOT always the true front window.
set indexOfTrueFrontWin to 1
repeat with ndx from 1 to wcount
if name of (item ndx of wapp_list) is name of wproc_current then
set indexOfTrueFrontWin to ndx
exit repeat
end if
end repeat
## log "true front index: " & indexOfTrueFrontWin
set ok to true
exit repeat
else
if (name of wproc_current) is wapp_targetName then
## log "processing: [" & name of wproc_current & "]"
tell wproc_current
set isFullScreen to get value of attribute "AXFullScreen"
if toggle then set turnOn to not isFullScreen
if isFullScreen is not turnOn then
## log "setting fullscreen to: " & turnOn
set value of attribute "AXFullScreen" to turnOn
delay 0.3 -- For good measure; it seems turning fullscreen *on* sometimes fails (you'll hear a pop sound).
else
## log "no change needed"
end if
end tell
set ok to true
exit repeat
else
## log "no match; waiting for '" & wapp_targetName & "', actual: '" & name of wproc_current & "'"
end if
end if
end try
end repeat
if not ok then error "Obtaining process window '" & wapp_targetName & "' of application " & appName & " timed out."
end if
end repeat
end tell
end tell
else if wcount > 0 then -- Target *current* window only (if there is one).
tell application "System Events"
tell process appName
# NOTE: We MUST activate the application in case its active window is in fullscreen mode.
# Bizzarrely, without activating, we would not gain access to that active window's *process* window.
set frontmost to true
set ok to false
repeat with attempt from 1 to MAX_TRIES
delay 0.2 -- Note: Only when the active window is currently in fullscreen mode are several iterations needed - presumably, because switching to that window's space takes time.
try
-- Obtain the same window as a *process* window, as only a process window allows us to examine or
-- change fullscreen status.
tell front window -- Note: This can fail before switching to a fullscreen space is complete.
set isFullScreen to get value of attribute "AXFullScreen"
if toggle then set turnOn to not isFullScreen
if isFullScreen is not turnOn then
set value of attribute "AXFullScreen" to turnOn
end if
end tell
set ok to true
exit repeat
end try
end repeat
if not ok then error "Obtaining active process window of application" & appName & " timed out."
end tell
end tell
end if
end setFullScreen
More background information:
The application windows collection - the one accessible in the context of a tell application ... block - always reports the total number of windows, whether they're in fullscreen mode or not. Unfortunately, such window objects canNOT be used to determine or set fullscreen mode - this must be done via the window objects reported by process objects in the context of the "System Events" application, as only they contain the relevant "AXFullScreen" attribute. It is important to note that the application windows collection - unlike the process windows collection - only works with applications that have AppleScript support.
Unfortunately, the window collection exposed by process objects in the context of the "System Events" application behaves strangely:
○ When an application is not frontmost or one of its NON-fullscreen windows is active, it only contains the NON-fullscreen windows
○ By contrast, when an application is frontmost and one of its fullscreen windows is active, it only ever contains that single fullscreen window, even if other windows (irrespective of whether they're fullscreen or not) exist.
○ Correlating application and process windows is tricky, because only application windows have an 'id' property; the only property the two types share directly is 'name' (i.e., the window title); both types also contains size information, though not in the same format.
○ (Also, process windows never include hidden windows, whereas the application-window collection must be filtered with whose visible is true to exclude hidden windows.)
As a result, if you want to process all windows of a given application, the basic approach is as follows:
○ Activate the application.
○ Loop over all (visible) application window objects.
○ Make each window the front window.
○ Wait for the corresponding process window to become programmatically accessible; this will take quite a while if the window activation involves a fullscreen transition.
○ Examine or change the fullscreen state of the process window (value of attribute "AXFullScreen").
If an application has only full-screen windows, AppleScript can get confused
over what the front window is: what it reports as the front window may not be
the one that is active when you activate the application with AppleScript or Cmd-tab to it.
When using activate to activate an application, a NON-fullscreen window of the target application will be activated, if there is one, even if a fullscreen window of that app was previously active.
You can, however, set the index of a fullscreen window to 1 to activate it.
if you want to toggle between fullscreen and normal mode use this hint
tell application "iTunes"
activate
tell application "System Events" to tell window "iTunes"
of application process "iTunes"
click (every button whose description contains "full screen")
end tell
end tell
You can detect full screen in Lion:
tell application "System Events"
tell process "Safari"
get value of attribute "AXFullScreen" of window 1
end tell
end tell
display dialog result as text
(from http://dougscripts.com/itunes/2011/07/detect-full-screen-mode/).
Another way to do this assuming you have not changed the default keyboard shortcut for "Enter Full Screen" is simply to have System Events invoke that shortcut (⌃⌘F). As with mklement0's wonderfully thorough answer, this requires making the relevant window active.
For instance, to toggle the full-screen state of the frontmost window in Safari, run:
tell application "Safari" to activate
tell application "System Events"
keystroke "f" using {command down, control down}
end tell
(Since the question was about Lion: I'm running macOS Sierra, but unless "Enter Full Screen" and "Exit Full Screen" are not available as menu options in Lion, I expect this would work in Lion as well. If the menu options are available in Lion but are not associated with a keyboard shortcut, it should be possible to add a shortcut under keyboard settings in System Preferences.)

Resources