Apple Music API - search songs and create playlist (MacOS) - applescript

I'm looking for API that would allow do these tasks
Search song in Apple Music
Create playlist
Add songs to playlist
Thanks in advance.

I'm afraid that what you are asking to do, is at the moment not possible since starting from iTunes 12.2 we can only search the local library and not the entire Apple Music from the API.
In the case you have the song that you want to play inside your library(local or cloud), you can search and play a song like this :
tell application "iTunes"
set results to (every track whose name contains "Cumuli" and artist is "883")
repeat with tune in results
play tune
end repeat
end tell
And then you can put the retrieved tune inside the playlist you want, or create a new one. Take a look at this post for an example.

Related

Applescript. Get properties of all instances

I have many instances of VLC open. I want to check the playing status of every instance like:
tell application "VLC"
if playing = true then return
end tell
But it checks only one instance of VLC. How can I check all instances?
This is a workaround answer based on your comment "I want to prevent a scheduled applescript to execute if a VLC instance is playing." and the other information that has been presented in other comments and answer posted prior to this one. Also, by execute, I'm assuming you mean execute any additional code in the script that started on schedule.
Also note, this may not be perfect however its being presented to give it a try.
On my system, when an occurrence of VLC is open and without content loaded, after the initial percent of CPU usage spikes it quickly settles to 0% and with content loaded but not playing it's less than 5% and typically less than 3%. If it's playing it's typically always greater than 5%.
This of course may vary on your system, so you'll need to monitor over a period of time polling CPU usage to see how it fluctuates on your system to see what the sweet spot is.
The following example AppleScript code when placed at the beginning of the code in the scheduled AppleScript, prior to code in your script to trigger whatever with VLC, will abort processing the rest of the script if the percent of CPU usage of other instances of VLC is equal to or greater than 5%.
set |VLC%CPU| to paragraphs of text of ¬
(do shell script "ps -Ac -o %cpu -o command | grep [V]LC ; exit 0")
repeat with thisItem in |VLC%CPU|
if first word of thisItem as integer ≥ 5 then return
end repeat
Another method could be to rename the instances by making copies of the application, and giving them new names such as VLC1, VLC2. You can do this by going to the applications folder and copying the VLC Application. Then paste it within the same folder to create the app "VLC copy". Then rename each copy you create. The copies will now show in the applescript dictionaries.
You can now use a tell block for each instance to check if it's playing. You just need to make sure that you open the correct instance numbers for the number you have playing. E.g. don't open "VLC1" and "VLC3" if you only have 2 instances, or close a lower instance number. By having the if c is equal to statement it won't open that instance of the application by executing the tell block.
If you have all instances open you could remove the loop and the if statements and just check if they're playing or not.
on getCount()
tell application "System Events"
set p to processes whose name contains "VLC"
set theCount to count of p
return theCount
end tell
end getCount
set appCount to my getCount()
if appCount is greater than 0 then
repeat with c from 1 to appCount
if c is equal to 1 then
tell application "VLC1"
if playing is true then
log ("playing 1")
end if
end tell
end if
if c is equal to 2 then
tell application "VLC2"
if playing is true then
log ("playing 2")
end if
end tell
end if
end repeat
end if
So far the half solution I do is:
tell application "System Events"
if (name of application processes whose frontmost is true) = {"VLC"} then return
end tell
So I check is it frontmost. Usually if I run a movie it is frontmost. I would prefer the "is playing" variation but... ok, what can I do.
I think I'm understanding the nature of your query more now. I was previously a little confused about what your objective was, but now I'm gathering it's simply to determine whether any VLC instance is playing or not. Is that correct ?
But that you do not need to know what is playing or in which window it's playing ?
And am I correct in saying that you only need to discover that a single instance out of many is playing, in which case this is sufficient to prevent some other AppleScript from executing ? Or, put another way, that other AppleScript will execute if and only if no instance of VLC is playing ?
I believe that's achievable. Although we can't use the playing property of the VLC application object, we can use properties/attributes of VLC processes/windows to determine whether or not each instance of VLC is playing.
tell application "System Events"
set _W to a reference to window 1 of (every process whose name is "VLC")
set _title to the value of attribute "AXTitle" of _W
end tell
That is literally all you need, as the AXTitle attribute returns very predictable data depending on the state of VLC:
▸ If VLC is playing and NOT fullscreen: _title evaluates to a non-empty string (specifically, it contains the name of the video file or the path to the internet stream).
▸ If VLC is NOT playing: _title evaluates to "VLC media player".
▸ If VLC is playing and IS fullscreen: _title evaluates to an empty string ("").
Therefore:
If _title = "VLC media player", then VLC is not playing; otherwise, VLC is playing.
Utilising this fact, in order for your other AppleScript to be allowed to execute, we want every _title value representing each instance of VLC to be equal to "VLC media player". If there is even one value in _title that is anything other than that, then the assertion fails and the script can terminate, or do whatever it needs to do to prevent the execution of some other script.
I chose to simply count the number of attributes returned with the name "AXTitle" and a value other than "VLC media player". The number returned is equal to the number of VLC instances currently playing:
tell application "System Events" to count ¬
(the attributes of window 1 of ¬
(every process whose name is "VLC") whose ¬
name is "AXTitle" and ¬
value is not "VLC media player")
if result is not 0 then return

In an Applescript file, how might I go about getting particular groups of albums to play at random

Say, only trying to get Artists → All Artists to play on random. Or playing Genre → Metal to play on random?
You can build a list selecting Artist or Genre and then play random item I of that list :
tell application "iTunes"
set MyList to every track whose genre is "pop"
set RandomNumber to random number from 1 to (count of MyList)
play item RandomNumber of MyList
end tell
However, you need to add a repeat loop to keep playing a next random number.
If you have iTunes version lower than 11, you can still use the shuffle property of a play list. Since version 11, shuffle property is obsolete. But Regulus663 found a workaround in stack overflow 4 years ago; refer to that link : How to set iTunes 11 in shuffle or repeat mode via applescript

Soundcloud script (VBS) to get related songs in Foobar playlist

The script was not written by me - it is a .vbs script for use in Foobar2000
https://gist.github.com/rornor/4d06d0994c1b8ae61ef5
The script queries the soundcloud.api and gets a list of songs based on a user or group. A dialogue pops up and asks for a username, search term, group, or URL, and it will load a group of songs into a temporary .pls file that it deletes after closing the player. I haven't much experience with .vbs so I can't give much information, but I can give the script here:
Screenshot of dialogue:
Click to enlarge
My question is
I would like it to build a related playlist like that the website does, so I choose one song and it loads the list of related songs into my Foobar Playlist. Is there a specific url I can load so it does that, or can I have it load from the API somewhere?
I've found an undocumented /related endpoint that can be used on a track object to get its "related" tracks
I'll be using this track as an example, which has an id of 107686148: https://soundcloud.com/maddecent/grandtheft-mobbin-feat
HTTP GET: https://api-v2.soundcloud.com/tracks/107686148/related?client_id={YOUR_CLIENT_ID}
The response from this api-v2 endpoint is an array of track objects which matche the related tracks shown in your web browser.
try this if you're working with WScript:
Dim Shell
Set Shell = CreateObject("WScript.Shell")
Shell.Run "soundcloud.com/tracks/00000/related?client_id=(your client id)"
that's a basic running mechanism in WScript but I'd like you to clarify a bit as I'm not sure what you mean by "loading songs into your playlist through vbscript".

Ensure one instance of an applescript is running

There is an screensaver that will launch scripts in OS X - which is great, but the problem I am having is that it launches multiple copies of the script. Is there a simple way to ensure that only one copy of this script is running at a time?
John Gruber wrote a post on something very similar to this a while back. Long story short, you would just wrap the entire thing in a block similar to the following:
tell application "System Events"
count (every process whose name is "BBEdit")
end tell
replacing "BBEdit" with your app name, and then launch only if the count is 0.

Applescript and iCal interaction

I'm trying to write an AppleScript to query iCal and find all the events I've got for a given date, in any calendar.
I started by writing a simple script that does something simple with every event in a given calendar:
tell application "iCal"
tell calendar "Reuniones"
set the_events to every event
repeat with an_event in the_events
-- do something with every event
set value to summary of an_event
end repeat
end tell
end tell
However, this simple script is taken a lot of time to execute (a few seconds), even if I'm not doing anything complex inside the loop. I'm afraid that the real script will really take a lot of time to execute.
I'm not very familiar with Applescript, and thus I imagine I'm doing something silly that has severe performance implications.
Can anybody explain me why this takes that much to execute? Can anybody suggest something to improve my code? I'm now going to start checking the date of the event, with a condition in the loop. I suspect there must be a way to search for events with a date (like the Automator action does), but I haven't been able to find a "native" way to do so ....
EDIT: I'm using Mac OS X Tiger (10.4). It is possible that newer versions of iCal have improved the library of operations available.
I've been grappling with this today and found that you can filter by date (at least on Snow Leopard). So
tell application "iCal"
set out to ""
set todaysDate to current date
set time of todaysDate to 0
repeat with c in (every calendar)
set theEvents to (every event of c whose start date ≥ todaysDate)
repeat with current_event in theEvents
set out to out & summary of current_event & "\n"
end repeat
end repeat
return out
end tell
will return the summary of all future events, and very quickly, compared to iterating through all events.
It isn't AppleScript, but the best of the bunch of other ways to do this seems to be iCalBuddy, which uses the public Cocoa APIs rather than parsing the calendar file directly and handles repeating events sensibly.
icalBuddy -nc -eed -iep title,datetime eventsToday+1
My initial intent was to select only the events for a given date, but apparently there aren't methods in iCal to access only the events for a specific day.
Thus, it is always necessary to go over all the events registered in every calendar. Even when interested in the events of a single calendar, say 'Today's Meetings", it is necessary to go through the entire set of events.
The best alternatives I've found around in the web don't use Apple Script, but instead they process the 'ics' files where the info is actually stored.
For reference, those files are located in '~/Library/ApplicationSupport/iCal'.

Resources