Advertisement
tommasz

get_current_track

Aug 23rd, 2023
1,677
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. global artistName, songName, albumName, songRating, songDuration, currentPosition, musicapp, apiKey, songMetaFile, mypath, currentCoverURL, isLoved
  2. set metaToGrab to {"artistName", "songName", "albumName", "songDuration", "currentPosition", "coverURL", "songChanged", "isLoved"}
  3. property enableLogging : false --- options: true | false
  4.  
  5. set apiKey to "2e8c49b69df3c1cf31aaa36b3ba1d166"
  6. try
  7.     set mypath to POSIX path of (path to me)
  8.     set AppleScript's text item delimiters to "/"
  9.     set mypath to (mypath's text items 1 thru -2 as string) & "/"
  10.     set AppleScript's text item delimiters to ""
  11. on error e
  12.     logEvent(e)
  13.     return
  14. end try
  15.  
  16. set songMetaFile to (mypath & "songMeta.plist" as string)
  17.  
  18.  
  19. if isMusicPlaying() is true then
  20.     my pruneCovers()
  21.     getSongMeta()
  22.     writeSongMeta({"currentPosition" & "##" & currentPosition})
  23.    
  24.     if didSongChange() is true then
  25.         delay 1
  26.         writeSongMeta({¬
  27.             "artistName" & "##" & artistName, ¬
  28.             "songName" & "##" & songName, ¬
  29.             "songDuration" & "##" & songDuration, ¬
  30.             "isLoved" & "##" & isLoved, ¬
  31.             "songChanged" & "##" & ¬
  32.             true})
  33.         if didCoverChange() is true then
  34.             set savedCoverURL to my readSongMeta({"coverURL"})
  35.             set currentCoverURL to grabCover()
  36.             if savedCoverURL is not currentCoverURL then writeSongMeta({"coverURL" & "##" & currentCoverURL})
  37.         end if
  38.         writeSongMeta({"albumName" & "##" & albumName})
  39.     else
  40.         writeSongMeta({¬
  41.             "songChanged" & "##" & false, ¬
  42.             "isLoved" & "##" & isLoved})
  43.     end if
  44. else
  45.     return
  46. end if
  47.  
  48. spitOutput(metaToGrab) as string
  49.  
  50. ------------------------------------------------
  51. ---------------SUBROUTINES GALORE---------------
  52. ------------------------------------------------
  53.  
  54. on isMusicPlaying()
  55.     set apps to {"Music", "Spotify"}
  56.     set answer to false
  57.     repeat with anApp in apps
  58.         tell application "System Events" to set isRunning to (name of processes) contains anApp
  59.         if isRunning is true then
  60.             try
  61.                 using terms from application "Music"
  62.                     tell application anApp
  63.                         if player state is playing then
  64.                             set musicapp to (anApp as string)
  65.                             set answer to true
  66.                         end if
  67.                     end tell
  68.                 end using terms from
  69.             on error e
  70.                 my logEvent(e)
  71.             end try
  72.         end if
  73.     end repeat
  74.     return answer
  75. end isMusicPlaying
  76.  
  77. on getSongMeta()
  78.     try
  79.         set musicAppReference to a reference to application musicapp
  80.         using terms from application "Music"
  81.             try
  82.                 tell musicAppReference
  83.                     set {artistName, songName, albumName, songDuration} to {artist, name, album, duration} of current track
  84.                     if musicapp is "Music" then
  85.                         set isLoved to loved of current track as string
  86.                     else if musicapp is "Spotify" then
  87.                         try
  88.                             set isLoved to starred of current track as string
  89.                         on error
  90.                             set isLoved to "false"
  91.                         end try
  92.                         set songDuration to my comma_delimit(songDuration)
  93.                     end if
  94.                     set currentPosition to my formatNum(player position as string)
  95.                     set songDuration to my formatNum(songDuration as string)
  96.                 end tell
  97.             on error e
  98.                 my logEvent(e)
  99.             end try
  100.         end using terms from
  101.     on error e
  102.         my logEvent(e)
  103.     end try
  104.     return songDuration
  105. end getSongMeta
  106.  
  107. on didSongChange()
  108.     set answer to false
  109.     try
  110.         set currentSongMeta to artistName & songName
  111.         set savedSongMeta to (readSongMeta({"artistName"}) & readSongMeta({"songName"}) as string)
  112.         if currentSongMeta is not savedSongMeta then set answer to true
  113.     on error e
  114.         my logEvent(e)
  115.     end try
  116.     return answer
  117. end didSongChange
  118.  
  119. on didCoverChange()
  120.     set answer to false
  121.     try
  122.         set currentSongMeta to artistName & albumName
  123.         set savedSongMeta to (readSongMeta({"artistName"}) & readSongMeta({"albumName"}) as string)
  124.         if currentSongMeta is not savedSongMeta then set answer to true
  125.         if readSongMeta({"coverURL"}) is "NA" then set answer to true
  126.     on error e
  127.         my logEvent(e)
  128.     end try
  129.     return answer
  130. end didCoverChange
  131.  
  132. on grabCover()
  133.     try
  134.         if musicapp is "Music" then
  135.             tell application "Music" to tell current track
  136.                 if exists (every artwork) then
  137.                     my getLocaliTunesArt()
  138.                 else
  139.                     my getLastfmArt()
  140.                 end if
  141.             end tell
  142.         else if musicapp is "Spotify" then
  143.             my getSpotifyArt()
  144.         end if
  145.     on error e
  146.         logEvent(e)
  147.         set currentCoverURL to getPathItem(mypath) & "default.png"
  148.     end try
  149.     return currentCoverURL
  150. end grabCover
  151.  
  152. on getLocaliTunesArt()
  153.     tell application "Music" to tell artwork 1 of current track -- get the raw bytes of the artwork into a var
  154.         set srcBytes to raw data
  155.         if format is «class PNG » then -- figure out the proper file extension
  156.             set ext to ".png"
  157.         else
  158.             set ext to ".jpg"
  159.         end if
  160.     end tell
  161.     set fileName to (mypath as POSIX file) & "cover" & (random number from 0 to 9) & ext as string -- get the filename to ~/my path/cover.ext
  162.     set outFile to open for access file fileName with write permission -- write to file
  163.     set eof outFile to 0 -- truncate the file
  164.     write srcBytes to outFile -- write the image bytes to the file
  165.     close access outFile
  166.     set currentCoverURL to POSIX path of fileName
  167.     writeSongMeta({"oldFilename" & "##" & currentCoverURL})
  168.     set currentCoverURL to getPathItem(currentCoverURL)
  169. end getLocaliTunesArt
  170.  
  171. on getSpotifyArt()
  172.     try
  173.         tell application "Music" to set currentCoverURL to artwork URL of current track
  174.     on error e
  175.         my logEvent(e)
  176.         set coverDownloaded to false
  177.         set rawXML to ""
  178.         set currentCoverURL to "NA"
  179.         repeat 5 times
  180.             try
  181.                 set rawXML to (do shell script "curl 'http://ws.audioscrobbler.com/2.0/?method=album.getinfo&artist=" & my textReplace(artistName, space, "+") & "&album=" & my textReplace(albumName, space, "+") & "&api_key=" & apiKey & "'")
  182.                 delay 1
  183.             on error e
  184.                 my logEvent(e & return & rawXML)
  185.             end try
  186.             if rawXML is not "" then
  187.                 try
  188.                     set AppleScript's text item delimiters to "extralarge\">"
  189.                     set processingXML to text item 2 of rawXML
  190.                     set AppleScript's text item delimiters to "</image>"
  191.                     set currentCoverURL to text item 1 of processingXML
  192.                     set AppleScript's text item delimiters to ""
  193.                     if currentCoverURL is "" then
  194.                         my logEvent("Cover art unavailable." & return & rawXML)
  195.                         set currentCoverURL to "NA"
  196.                         set coverDownloaded to true
  197.                     end if
  198.                 on error e
  199.                     my logEvent(e & return & rawXML)
  200.                 end try
  201.                 set coverDownloaded to true
  202.             end if
  203.             if coverDownloaded is true then exit repeat
  204.         end repeat
  205.     end try
  206. end getSpotifyArt
  207.  
  208. on pruneCovers()
  209.     try
  210.         do shell script "rm '" & readSongMeta({"oldFilename"}) & "'"
  211.     on error e
  212.         my logEvent(e)
  213.     end try
  214. end pruneCovers
  215.  
  216. on getPathItem(aPath)
  217.     set AppleScript's text item delimiters to "/"
  218.     set countItems to count text items of aPath
  219.     set start to countItems - 2
  220.     set outputPath to "/" & text items start thru -1 of aPath as string
  221.     set AppleScript's text item delimiters to ""
  222.     return outputPath
  223. end getPathItem
  224.  
  225. on readSongMeta(keyNames)
  226.     set valueList to {}
  227.     tell application "System Events" to tell property list file songMetaFile to tell contents
  228.         repeat with keyName in keyNames
  229.             try
  230.                 set keyValue to value of property list item keyName
  231.             on error e
  232.                 my logEvent("Reading song metadata" & space & e)
  233.                 my writeSongMeta({keyName & "##" & "NA"})
  234.                 set keyValue to value of property list item keyName
  235.             end try
  236.            
  237.             copy keyValue to the end of valueList
  238.         end repeat
  239.     end tell
  240.     return valueList
  241. end readSongMeta
  242.  
  243. on writeSongMeta(keys)
  244.     tell application "System Events"
  245.         if my checkFile(songMetaFile) is false then
  246.             -- create an empty property list dictionary item
  247.             set the parent_dictionary to make new property list item with properties {kind:record}
  248.             -- create new property list file using the empty dictionary list item as contents
  249.             set this_plistfile to ¬
  250.                 make new property list file with properties {contents:parent_dictionary, name:songMetaFile}
  251.         end if
  252.         try
  253.             repeat with aKey in keys
  254.                 set AppleScript's text item delimiters to "##"
  255.                 set keyName to text item 1 of aKey
  256.                 set keyValue to text item 2 of aKey
  257.                 set AppleScript's text item delimiters to ""
  258.                 make new property list item at end of property list items of contents of property list file songMetaFile ¬
  259.                     with properties {kind:string, name:keyName, value:keyValue}
  260.             end repeat
  261.         on error e
  262.             my logEvent(e)
  263.         end try
  264.     end tell
  265. end writeSongMeta
  266.  
  267. on spitOutput(metaToGrab)
  268.     set valuesList to {}
  269.     repeat with metaPiece in metaToGrab
  270.         set valuesList to valuesList & readSongMeta({metaPiece}) & " @ "
  271.     end repeat
  272.     set output to items 1 thru -2 of valuesList
  273.     return output
  274. end spitOutput
  275.  
  276. on formatNum(aNumber)
  277.     set delimiters to {",", "."}
  278.     repeat with aDelimiter in delimiters
  279.         if aNumber contains aDelimiter then
  280.             set AppleScript's text item delimiters to aDelimiter
  281.             set outValue to text item 1 of aNumber
  282.             set AppleScript's text item delimiters to ""
  283.             return outValue
  284.         end if
  285.     end repeat
  286.     if aNumber does not contain delimiters then return aNumber
  287. end formatNum
  288.  
  289. on comma_delimit(this_number)
  290.     set this_number to this_number as string
  291.     if this_number contains "E" then set this_number to number_to_string(this_number)
  292.     set the num_length to the length of this_number
  293.     set the this_number to (the reverse of every character of this_number) as string
  294.     set the new_num to ""
  295.     repeat with i from 1 to the num_length
  296.         if i is the num_length or (i mod 3) is not 0 then
  297.             set the new_num to (character i of this_number & the new_num) as string
  298.         else
  299.             set the new_num to ("." & character i of this_number & the new_num) as string
  300.         end if
  301.     end repeat
  302.     return the new_num
  303. end comma_delimit
  304.  
  305. on number_to_string(this_number)
  306.     set this_number to this_number as string
  307.     if this_number contains "E+" then
  308.         set x to the offset of "." in this_number
  309.         set y to the offset of "+" in this_number
  310.         set z to the offset of "E" in this_number
  311.         set the decimal_adjust to characters (y - (length of this_number)) thru ¬
  312.             -1 of this_number as string as number
  313.         if x is not 0 then
  314.             set the first_part to characters 1 thru (x - 1) of this_number as string
  315.         else
  316.             set the first_part to ""
  317.         end if
  318.         set the second_part to characters (x + 1) thru (z - 1) of this_number as string
  319.         set the converted_number to the first_part
  320.         repeat with i from 1 to the decimal_adjust
  321.             try
  322.                 set the converted_number to ¬
  323.                     the converted_number & character i of the second_part
  324.             on error
  325.                 set the converted_number to the converted_number & "0"
  326.             end try
  327.         end repeat
  328.         return the converted_number
  329.     else
  330.         return this_number
  331.     end if
  332. end number_to_string
  333.  
  334. on textReplace(sourceText, searchText, replaceText)
  335.     set {TID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, searchText}
  336.     set textItems to every text item of sourceText
  337.     set AppleScript's text item delimiters to replaceText
  338.     set changedText to textItems as string
  339.     set AppleScript's text item delimiters to TID
  340.     return changedText
  341. end textReplace
  342.  
  343. on encodeText(this_text, encode_URL_A, encode_URL_B, method)
  344.     --http://www.macosxautomation.com/applescript/sbrt/sbrt-08.html
  345.     set the standard_characters to "abcdefghijklmnopqrstuvwxyz0123456789"
  346.     set the URL_A_chars to "$+!'/?;&@=#%><{}[]\"~`^\\|*"
  347.     set the URL_B_chars to ".-_:"
  348.     set the acceptable_characters to the standard_characters
  349.     if encode_URL_A is false then set the acceptable_characters to the acceptable_characters & the URL_A_chars
  350.     if encode_URL_B is false then set the acceptable_characters to the acceptable_characters & the URL_B_chars
  351.     set the encoded_text to ""
  352.     repeat with this_char in this_text
  353.         if this_char is in the acceptable_characters then
  354.             set the encoded_text to (the encoded_text & this_char)
  355.         else
  356.             set the encoded_text to (the encoded_text & encode_char(this_char, method)) as string
  357.         end if
  358.     end repeat
  359.     return the encoded_text
  360. end encodeText
  361.  
  362. on encode_char(this_char, method)
  363.     set the ASCII_num to (the ASCII number this_char)
  364.     set the hex_list to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}
  365.     set x to item ((ASCII_num div 16) + 1) of the hex_list
  366.     set y to item ((ASCII_num mod 16) + 1) of the hex_list
  367.     if method is 1 then
  368.         return ("%" & x & y) as string
  369.     else if method is 2 then
  370.         return "_" as string
  371.     end if
  372. end encode_char
  373.  
  374. on checkFile(myfile)
  375.     try
  376.         POSIX file myfile as alias
  377.         return true
  378.     on error
  379.         return false
  380.     end try
  381. end checkFile
  382.  
  383. on logEvent(e)
  384.     if enableLogging is true then
  385.         set e to e as string
  386.         do shell script "echo '" & (current date) & space & e & "' >> ~/Library/Logs/CurrentTrack.log"
  387.     else
  388.         return
  389.     end if
  390. end logEvent
Tags: AppleScript
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement