When copying music files from one iTunes library to another, things like track play count, rating and enabled are lost,
This can be annoying, especially when several thousand tracks are involved.
Here are a pair of scripts, the first of which saves these track parameters to a text file (UTF-16), and a second which looks through an iTunes library for tracks which match entries in the text file, and sets their play count, star rating, and enabled state to match.
(*
SaveTrackIDPlayCount-Rating-Enabled.scpt
BP 2015
Make a file that lists every track in iTunes library
Use combined name, time and size string as a unique identifier for each track
follow that with rating, playcount and enabled each separated by returns
Use Unicode for the file (UTF-16) so unique identifiers don't get mangled for tracks with non-Roman characters
TextEdit won't read this file correctly, but TextWrangler can be set to interpret UTF-16 text
properly.
This script expects a folder named "result" to be in place on the desktop.
If it's not there, it tries to make one.
That's where the results file lives, where RestoreTrackIDPlayCount-Rating-Enabled.scpt
can get at it.
If it can't find or make the folder, the script will not run.
The script takes a while to run, so it tells you each time it processes 4000 tracks
Other Properties of tracks, such as 'lyrics', or 'volume adjustment' can be added to this
basic script, and with mirror changes to the "RestoreTrackIDPlayCount-Rating-Enabled.scpt"
will be mirrored to the new music library.
--
Using a 2D list for gathering data takes 38.5 times as long for 20000 tracks: 11107 sec vs 288 sec (4097 sec for 120K tracks, so it does slow down)
writing the file as r=text is 100 times faster than parsing and writing a list 0 vs 100 sec for 20K tracks 0 sec for 129K tracks
*)
set destfolder to (path to desktop as string) & "result:"
set outputfilename to "tracksstarsplaycountsandenabled"
tell application "Finder"
if (folder destfolder exists) is false then
make new folder at desktop with properties {name:"result"}
end if
delay 1
if (folder destfolder exists) is false then
say "beep"
display dialog "Couldn't make folder on Desktop."
return
end if
end tell
tell application "iTunes"
--set t1 to current date
say "begin"
set thetracks to every track -------------------------------- This can take a while. 40 sec for 20000 tracks
set trackct to count of thetracks
--set elapsed to (current date) - t1
--display dialog elapsed
set t1 to current date
set trakdat to ""
repeat with n from 1 to trackct
-- This next 'line' is the place to add additional infor you want saved:
-- For what's possible, look at iTunes' AppleScript dictionary
set trakdat to (trakdat & (name of item n of thetracks & ((time of item n of thetracks) as text)) & ((size of item n of thetracks) as text)) & "
" & ((rating of item n of thetracks) as text) & "
" & ((played count of item n of thetracks) as text) & "
" & (((enabled of item n of thetracks) as integer) as text) & "
"
if n mod 4000 is equal to 0 then say n ------------------------------- progress indicator
end repeat
--end using terms from
end tell
set elapsed to (current date) - t1
--display dialog elapsed
set OK to WriteAFile(trakdat, destfolder, outputfilename)
say "beep"
display dialog "Finished"
return trakdat
------
------
on WriteAFile(thetext, dst, outputfilename)
set writeit to true
set filpath to dst & outputfilename -- no extension
set t1 to current date
try
set fileID to open for access file filpath with write permission
on error result
display dialog result -- let em know whats wrong
set writeit to false
try
close access file filpath -- let this fail silently
end try
end try
if writeit then
set eof file filpath to 0
write thetext to file filpath as Unicode text -- <--- specify the format
end if
try
close access file filpath -- let this fail silently
end try
set elapsed to (current date) - t1
--display dialog elapsed
return writeit
end WriteAFile
------
------
(*
RestoreTrackIDPlayCount-Rating-Enabled.scpt
BP 2015
SetPlaycountandRatingFromFile
Specifically the file generated by "SaveTrackIDPlayCount-Rating-Enabled.scpt"
This script expects a folder named "result" to be in place on the desktop,
with a file in it called "tracksstarsplaycountsandenabled"
The script takes a while to run, so it tells you each time it processes 4000 tracks
*)
set oldtid to AppleScript's text item delimiters
set AppleScript's text item delimiters to "
"
set filpath to (path to desktop as string) & "result:" & "tracksstarsplaycountsandenabled"
set thetext to Getthetext(filpath) -- This gets me the data as a block of return delimited text
set textlen to count of thetext
if textlen is less than 4 then
say "Beep"
display dialog "There's no valid tracklist in the result folder"
return -- We got nothing -- Otherwise assume we have a useful file
end if
--- loop through for every track
tell application "iTunes"
set trackct to count of every track
say "start"
set t1 to current date
set trakdat to ""
end tell
repeat with n from 1 to trackct
tell application "iTunes" to set targetID to (trakdat & ((name of track n & (time of track n) as text) & ((size of track n) as text)))
set tlst to {}
set tlst to GetRatingPlaysandEnabled(targetID, thetext, textlen)
--return tlst
if item 4 of tlst is equal to 1 then
-- the following lines actually do the restore
-- you can comment out the ones you don't care about for more speed
-- or add more lines if you've suitably modded SaveTrackIDPlayCount-Rating-Enabled.scpt
tell application "iTunes" to set rating of track n to item 1 of tlst
tell application "iTunes" to set played count of track n to item 2 of tlst
tell application "iTunes" to set enabled of track n to item 3 of tlst
end if
if n mod 4000 is equal to 0 then say n ------------------------------- progress indicator
end repeat
--end using terms from
--end tell
set elapsed to (current date) - t1
--display dialog elapsed
--- end of loop through for every track
set AppleScript's text item delimiters to oldtid
return
-----
-----
on GetRatingPlaysandEnabled(targetID, thetext, textlen)
set rating to 0
set playcount to 0
set enabld to true
set itsinthere to 0
set z to 0
set z to offset of targetID in thetext
try
if z is greater than 0 then
set itsinthere to 1
set z to z + (length of targetID) + 1 -- 1 is for the return
set tstrend to z + 32 -- no one has 20 some digits worth of play count
if tstrend is greater than textlen then set tstrend to textlen
set tstr to text z through tstrend of thetext -- need to limit to textlen
set tlst to every text item of tstr
set rating to item 1 of tlst as integer
set playcount to item 2 of tlst as integer
set enabld to true
if ((item 3 of tlst) as integer) is equal to 0 then set enabld to false
else
set itsinthere to 0 -- there is no such track
end if
end try
return {rating, playcount, enabld, itsinthere}
end GetRatingPlaysandEnabled
-----
-----
on Getthetext(filpath)
set sometext to ""
try
get info for file filpath -- Std additions make sure the files there or
-- Open for access will create an empty file and confuse me
on error result
beep 1
return sometext
end try
try
set sometext to read file filpath from 1 as Unicode text -- <-- specfy format
on error result number errorNumber
if errorNumber is not equal to -39 then -- empty files give an eof error
display dialog of result buttons {"OK"} default button 1 with icon caution -- empty or nonexistent files give an eof error
end if
try
close access file filpath
end try
end try
try
close access file filpath -- let this fail silently
end try
return sometext -- returns empty list on error
end Getthetext
-----
-----
I’ve used these scripts to use as part of the process of downdating my iTunes version from 12.1 to the more user friendly 10 point something (which runs fine under OS X 10.10.4).
I’ve no idea how iTunes match or other iTunes cloud services will affect the running of these scripts, as I don’t use any such services. All my music is there, in my music library as complete files.
With a little effort, these scripts could be converted so as data is only collected/restored for a single playlist at a time, but that was not my purpose in writing the things.