Last active
November 22, 2024 15:53
-
-
Save iamkirkbater/bd90733c5b24abd33a027936265ce270 to your computer and use it in GitHub Desktop.
Applescript - Get Currently Playing Track information from Apple Music and write to file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use scripting additions | |
use framework "Foundation" | |
-- Set Configuration Defaults | |
set OUTPUT_FILE to "~/now-playing.json" | |
-- END Configuration | |
on getCurrentTrack() | |
tell application "Music" | |
if it is running then | |
try | |
set currentTrack to (get current track) | |
set trackName to name of currentTrack as text | |
on error m number n | |
set trackName to "XX" | |
end try | |
else | |
set trackName to "XX" | |
end if | |
end tell | |
return trackName | |
end getCurrentTrack | |
on getTrackInfo() | |
set processImage to 1 | |
set trackName to "" | |
set playerState to "" | |
set trackArtist to "" | |
set trackAlbum to "" | |
set trackDuration to 0 | |
set coverArt to "" | |
set imgFormat to "" | |
try | |
with timeout of 2 seconds | |
tell application "Music" | |
if it is running then | |
set playerState to player state as text | |
try | |
set currentTrack to (get current track) | |
set trackName to name of currentTrack as text | |
set trackArtist to artist of currentTrack as text | |
set trackAlbum to album of currentTrack as text | |
set trackDuration to duration of currentTrack | |
set artObj to (get artwork 1 of currentTrack) | |
set imgFormat to my getImgFormat(artObj) | |
set rawArtData to (get raw data of artObj) | |
on error m number n | |
set processImage to 0 | |
end try | |
end if | |
end tell | |
end timeout | |
end try | |
-- Get CoverArt as base64 string to include in output | |
if processImage is equal to 1 then | |
set coverArt to my getBase64ImageString(imgFormat, rawArtData) | |
end if | |
set output to {player_state:playerState, track_info:{track:trackName, artist:trackArtist, album:trackAlbum, duration:trackDuration, album_art:coverArt}} | |
return output | |
end getTrackInfo | |
on getImgFormat(format) | |
set imgFormat to "" | |
if format is JPEG picture then | |
set imgFormat to ".jpg" | |
else | |
set imgFormat to ".png" | |
end if | |
return imgFormat | |
end getImgFormat | |
on getBase64ImageString(format, rawArtData) | |
-- todo - can we do this without constantly writing to /tmp? | |
set artPath to "/tmp/albumArt" & format as text | |
try | |
tell me to set fileRef to (open for access artPath with write permission) | |
write rawArtData to fileRef starting at 0 | |
tell me to close access fileRef | |
on error m number n | |
log n | |
log m | |
try | |
tell me to close access fileRef | |
end try | |
end try | |
set encArt to (do shell script "base64 < " & artPath) | |
set coverArt to ("data:" & format & ";base64," & encArt) as string | |
end getBase64ImageString | |
on refreshTrackInfo(OUTPUT_FILE) | |
set trackInfo to getTrackInfo() | |
set jsonString to convertToJson(trackInfo) | |
writeString(jsonString, OUTPUT_FILE) | |
end refreshTrackInfo | |
on convertToJson(track) | |
set objCDictionary to current application's NSDictionary's dictionaryWithDictionary:track | |
set {jsonDictionary, anError} to current application's NSJSONSerialization's dataWithJSONObject:objCDictionary options:0 |error|:(reference) | |
if jsonDictionary is missing value then | |
log "An error occured: " & anError as text | |
else | |
set jsonString to (current application's NSString's alloc()'s initWithData:jsonDictionary encoding:(current application's NSUTF8StringEncoding)) as text | |
end if | |
return jsonString | |
end convertToJson | |
on writeString(str, outputFile) | |
do shell script "echo " & quoted form of str & " > " & outputFile | |
end writeString | |
on main(OUTPUT_FILE) | |
set previousTrack to "XX" | |
set currentTrack to "" | |
refreshTrackInfo(OUTPUT_FILE) | |
repeat while true | |
set currentTrack to getCurrentTrack() | |
if previousTrack is not currentTrack then | |
refreshTrackInfo(OUTPUT_FILE) | |
set previousTrack to currentTrack | |
end if | |
delay 2 | |
end repeat | |
end main | |
main(OUTPUT_FILE) |
Revision 2 - Abstracts the base64 image string conversion to its own function.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Revision 1 - Only writes new files if the track changes. Removes progress functionality (will be gained elsewhere, to reduce write operations), adds support for the Music App being open but having nothing currently "playing", i.e. no track paused or queued up yet.