How to get current playing song on mac by command line tools? - macos

I can only find some applescripts on Google with specific music app(like itunes, spotify, etc) to get current playing song.
But now I'm using Netease Music which not supporting to be controled by applescript, I wonder if there is any universal way to get current playing song info via mac media center?
Applescript and other command line tools both ok.

I made a cli tool that lets you read properties from the private MediaRemote framework.
https://github.com/kirtan-shah/nowplaying-cli
Since it uses private APIs, it may break with future macOS updates but is currently working on Ventura 13.1.
Here is an example that will retrieve the song name:

This following AppleScript code uses UI scripting to retrieve the currently playing media.
tell application "System Events" to tell process "Control Center"
click menu bar item "Control Center" of menu bar 1
set currentlyPlaying to value of static text 3 of window "Control Center"
key code 53 -- press 'esc' key
end tell
activate
display dialog currentlyPlaying with title "Currently Playing" buttons ¬
{"OK"} default button 1 giving up after 3

Related

Is there a way to pause a YouTube video in Google Chrome using AppleScript?

What I'm trying is to type tell application "Google Chrome" to pause and make audio or video in Google Chrome pause. It wouldn't work, since it thinks pause is a variable.
Is there any way to either pause audio or video in all applications or just Google Chrome?
From comments:
The following example AppleScript code will play/pause a YouTube video in the active tab of the front window of Google Chrome: tell application "Google Chrome" to tell active tab of front window to execute javascript "document.getElementsByClassName('ytp-play-button ytp-button')[0].click();"
#user3439894 this one works perfectly, since I only want to pause the video in the active tab. Is there any way to check if the video is paused so it doesn't unpause a video? Also could you write this comment as an answer so I can accept it as the correct answer?
There may be an easier way using JavaScript to ascertain if the active tab of the front window in Google Chrome has a YouTube video playing, however, as I do not know the code for it, here is a way that works for me.
The following example AppleScript code, shown below, was tested in Script Editor under macOS Catalina 10.15.7 and macOS Big Sur 11.2.3 using Google Chrome (Version 90.0.4430.93 (Official Build) (x86_64)) with Language & Region settings in System Preferences set to English (US) — Primary and worked for me without issue1.
1 Assumes necessary and appropriate setting in System Preferences > Security & Privacy > Privacy have been set/addressed as needed.
Example AppleScript code:
if not running of ¬
application "Google Chrome" then return
tell application "Google Chrome"
if (window count) = 0 then return
set atx to the active tab index of its front window
end tell
tell application "System Events"
-- # macOS Big Sur System Events bug issue.
-- # If running macOS Big Sur, uncomment the next
-- # two lines if System Events reports an error.
-- run
-- delay 0.5
tell application process "Chrome"
if (the value of ¬
attribute "AXTitle" of ¬
radio button atx of ¬
tab group 1 of ¬
group 1 of ¬
the front window) ¬
does not end with "Audio playing" then return
end tell
end tell
tell application "Google Chrome" to ¬
tell the active tab of its front window to ¬
execute javascript ¬
"document.getElementsByClassName('ytp-play-button ytp-button')[0].click();"
Notes:
As coded, the execute javascript only happens if there is a YouTube video playing in the active tab of the front window of Google Chrome, thus pausing it. The code, as coded, cannot cause a paused video to play, regardless of the active tab or any tab of any window.
The -- # macOS Big Sur System Events bug issue. section in the example AppleScript code is an attempted workaround to a System Events issue in macOS Big Sur, in that the exact same code without it runs without issue in macOS Catalina and may not work or needs adjusting. I am still trying to troubleshoot the issue in general. In my experience the issue has not been reproducible at will and as such alternate methods may have to be used if issue continues and cannot be diagnosed.
Use of other than exact versions tested under may be partially to blame for some errors, especially any that involve a change in the hierarchical UI element structure in any UI Scripting scenario using System Events.
Is there any way to either pause audio or video in all applications or just Google Chrome?
Typically pressing the Play/Pause key on the keyboard should pause a video in Google Chrome, and most other apps as well.
It wouldn't work, since it thinks pause is a variable.
pause is not part of the AppleScript dictionary in Google Chrome and why it shows as a variable.
In Google Chrome, running AppleScript code containing JavaScript needs the Allow JavaScript from Apple Events menu item checked under: View > Developer -- Note that this used to be the default, however, at some time is was changed. For more information: https://support.google.com/chrome/?p=applescript
Note: The example AppleScript code is just that and sans any included error handling does not contain any additional error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors. Additionally, the use of the delay command may be necessary between events where appropriate, e.g. delay 0.5, with the value of the delay set appropriately.
This following AppleScript code will pause or play any instance of a YouTube video in any tab of any window in Google Chrome (whether visible or not).
pauseOrPlayYoutubeInChrome("ytp-play-button ytp-button", 0)
to pauseOrPlayYoutubeInChrome(theClassName, elementnum)
tell application "Google Chrome"
set youtubeTabsRef to a reference to (tabs of windows whose URL contains "youtube")
repeat with youtubeTabs in youtubeTabsRef
execute youtubeTabs javascript "document.getElementsByClassName('" & ¬
theClassName & "')[" & elementnum & "].click();"
end repeat
end tell
end pauseOrPlayYoutubeInChrome
My solution consists of running 2 AppleScript in a specific environment.
It works for me using 1 window of Brave Browser(I think it is the same for google chrome) with 2 tabs on youtube.
First script force opening Brave browser, second run keystroke "K"
tell application "Brave Browser"
if it is not running then launch
activate
end tell
tell application "System Events"
keystroke "k"
end tell
I have created a Quick Action on Automator and then I have followed this answer: https://apple.stackexchange.com/a/401262
And when trying to test it as a Keyboard Shortcut when using another Application, I was receiving an error like this "com.automator.runner.xpc is not allowed to send keystrokes", so I realised that I need to give accessibility privileges(on Security and Privacy) to all applications I want the script to work.
And After that, it works, but sometimes it gives the same error and it works again after some minutes(and never come back again) so I think this can help someone too.
This will pause or play the youtube video on the tab of the Brave Browser that is active.

How to find a specific tab while multiple Google Chrome windows are open in AppleScript

to clickClassName(theClassName, elementnum)
tell application "Google Chrome"
set youtubeTab to (the first tab of window 2 whose URL contains "youtube")
end tell
tell application "Google Chrome"
execute youtubeTab javascript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();"
end tell
end clickClassName
clickClassName("ytp-play-button ytp-button", 0)
I have two windows open on my MacBook. One on the MacBook itself another one on the external display. I would like to play/pause YouTube videos playing on the external display while taking notes on my MacBook. Above script works only if the windows on the MacBook is activated because it is specifically pointing to the other window via window 2.
I think I need to find all windows and somehow use the repeat operator so that I can play/pause the video regardless of which window is activated. But I am not sure how to approach.
Any help is appreciated!
PS. I have added this script as a Service and assigned a specific key combination. So when I am taking notes on my MacBook I can quickly play/pause the video.
The following example AppleScript code will click the Play/Pause button on a YouTube video in any (every) tab of Google Chrome whose URL contains youtube:
tell application "Google Chrome"
set YouTubeTabs to a reference to ¬
(tabs of windows whose URL contains "youtube")
repeat with aTab in YouTubeTabs
tell aTab to ¬
execute javascript ¬
"document.getElementsByClassName('ytp-play-button ytp-button')[0].click();"
end repeat
end tell
Assuming you only have one tab in Google Chrome that has a YouTube video to play/pause, this will certainly do it for you.

AppleScript for AirPlay Button in the new TV app

Can anybody figure out how to click the AirPlay Display pop up button in the new TV app (found in MacOS Catalina) using AppleScript? I've tried a zillion different ways, and still get the result "missing value."
As far as I know this code should work:
tell application "System Events"
tell application process "TV"
tell window 1
click ((button whose description is "airplay") of pop up button 1)
end tell
end tell
end tell
Here is a picture of the Accessibility Inspector for that pop up button:
UPDATE: Apparently the new TV app in Catalina is not fully scriptable. AppleScript support for AirPlay Displays does not exist (neither directly nor through GUI scripting). Hopefully, Apple will add support in the future...

How to click on a button in an app from the status bar with Apple Script

I have see how to click on menu items but this application does not have those. I was wondering how to click on the button Connect
I tried click at {818, 320} but it did not work
Here is the scrip, i was able to open the app with this
tell application "System Events"
tell UI element "Hotspot Shield"
tell menu bar item 1 of menu bar 2
click
delay 2
get the actions of button "Connect"
end tell
end tell
end tell
FWIW One would not normally use tell UI element "Hotspot Shield" rather use tell application process "Hotspot Shield", however, looking at this through Accessibility Inspector, I do not see a way to click the "Connect" button. Even using a Watch Me Do action in Automator, while it will record the process, it won't play it back successfully.
That said, here is a workaround solution that works for me on macOS Mojave using AppleScript and the third-party command line utility Cliclick.
Looking at the cropped screen shot in your OP and using the approximate center of the Connect button to be at 320 for the y axis and using AppleScript to get the position of the menu bar item for use as the approximate x axis, the following example AppleScript code should work for you too.
tell application "System Events" to ¬
tell application process "Hotspot Shield" to ¬
tell menu bar item 1 of menu bar 2
set xPos to first item of (get its position)
click
end tell
delay 0.5
do shell script "/Applications/cliclick c:" & xPos & ",320"
Note that the value of the delay command may need to be adjusted to ensure the Connect button is visible before the click event takes place using cliclick.
Adjust the path to cliclick as needed. I placed it in /Applications just for testing purposes.
The usual caveats, regarding System Preferences > Security & Privacy > Privacy, apply.
I am not affiliated with the developer of Cliclick, just a satisfied user of the product.
Note: The example AppleScript code is just that and does not contain any error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors.

Access context menu items by name using AppleScript

I'm trying to use AppleScript to click on context menu items in Logic Pro, preferably by simply providing the name of the menu item. It seems like this should be possible because I'm able to set up keyboard shortcuts for these context menu items using system preferences and providing the name of the command.
For instance, if you right click on the main editing window in Logic, a menu pops up with an option called "Add Audio File..." If I create a system preferences keyboard shortcut for Logic and give it this menu item name, it's able to execute just fine. I'd like to recreate this with a script. I'm familiar with accessing normal menu items using the hierarchy like so:
tell process "Logic Pro"
tell menu bar 1
tell menu bar item "File"
tell menu "File"
click menu item "Save"
but as far as I know, there's no way to access the context menu (right click menu) that I want like this. It seems there should be a way to simply access a non-menu-bar menu item by name since system preferences is obviously able to do so.
Logic pro is not scriptable so my suggestion would be that you set a keyboard shortcut in the system preferences then use system events to use said shortcuts.
for example to enter find mode (assuming there is a find mode since i don't own Logic Pro)
tell application "Logic Pro" to activate
tell application "System Events"
tell application process "Logic Pro"
keystroke "f" using command down
end tell
end tell
I don’t think you need to use the context menus. “Add Audio File…” is available in other parts of the Logic Pro X user interface. If you open the Project Audio window, there is an “Audio File” menu button with an “Add Audio File…” button in it. So this AppleScript will activate the “Add Audio File…” command:
tell application "System Events"
tell application "Logic Pro X" to activate
tell process "Logic Pro X"
tell menu bar 1
click menu item "Open Project Audio" of menu "Window"
end tell
delay 1
tell window 1
click menu button "Audio File" of group 1 of group 1
click menu item "Add Audio File..." of menu 1 of menu button "Audio File" of group 1 of group 1
end tell
end tell
end tell
One thing to keep in mind if distributing a GUI script is that the above script will only work in Logic Pro X running on a Mac set to US English (and maybe other kinds of English) because the names of the menus change if the system is set to another language. What you can do is replace the names in the above script with numbers, which is a totally experimental process, as far as I know. You have to try different numbers and see which continues to work.
So you may be able to replace:
menu button "Audio File" of group 1 of group 1
… in the above script with:
menu button 1 of group 1 of group 1
… and get the same functionality, and the script would work on any Mac. Or you may need to use “menu button 2.” Same goes for the other named items in the above script.
Also keep in mind that the user you distribute this script to has to give System Events permission to control their Mac in the Security pane of System Preferences or this script won’t work. That can be a giant obstacle to distributing GUI scripts. And if you save your script as an Application, you have to digitally sign it or it won’t run on other people’s computers, and that can be complicated.

Resources