Loading playlist

This topic starts with iTunes and continues in Music.app.

I wrote an AppleScript a while ago in iTunes in Mojave. Essentially it grabbed the tracks of a playlist and manipulated the information to ‘export’ tracks etc to a USB drive for use in-car. A single command gets all the data for the entire playlist into AppleScript lists which it then iterates through to do its stuff. Grabbing an entire playlist of 25k tracks took seconds and thereafter, no AppleEvents to slow things down. All worked perfectly, then I updated my Mac Pro to Monterey and of course Music.app.

After weeks of massaging my music collection back into shape after the appallingly poor import attempts of Music, I tried to run my script, having changed all app references to Music. It doesn’t work.

The problem is that whereas iTunes can grab data for 25k tracks in a couple of seconds, Music takes many minutes and then there’s an AppleEvents timeout and Music is apparently hung (‘application not responding’) for quite some time.

So I increased the AppleEvents timeout (using ‘with timeout’) to an hour. Now it just takes an hour before the same timeout error.

It is that one command grabbing all the playlist’s tracks causing the problem. To test it, I’ve copied it to another new script that does nothing else and it is unable to complete the task that takes mere seconds in iTunes.

tell application "Music" to set {albArts, sortAlbArts, Albs, SortAlbs, locations} to {album artist, sort album artist, album, sort album, location} of file tracks in currPL

where currPL is the currently selected playlist in Music. As I said, this has always worked perfectly in iTunes taking only a couple of seconds, but fails in Music - most of the time. It has completed a couple of times, then fails again with an AppleEvents timeout. No apparent reason why there is this inconsistency as nothing is changed in the meantime.

Has anyone come across this obstacle in Music? Is there something to be done that will prevent it, or perhaps another way to achieve the same thing? I will of course be trying to come up with an alternative myself, but if someone already has the solution, it would be much appreciated if they could let me know what it is.

A quick addition…

While creating this topic, I ran my script and it timed out. I waited until Music had ‘unhung’ itself and Quit Music. Started Music and ran the script again which completed without issue. Ran it again with a slightly smaller playlist (20k rather than 25k track) and again, it completed without error.

When I actually started this topic, I had been unable to get it to complete, after multiple attempts. With Music running (doing nothing) I put the Mac to sleep overnight and tried my script again the next morning and it ran without error. So it didn’t look like Music was running out of memory if open for a long time.

However, as mentioned above, after it failed again this morning, I Quit and restarted Music which then ran twice without problem.

I cannot see any logic in why it may or may not fail, but it looks like it either completes that particular command I included in the first post in about 10-12 seconds, or if it is taking longer than that, it will never complete. So something can trip it up, but not every time. With a single one line command, working on the same data every time, how can Music be so inconsistent and unreliable in its operation. To be honest, this is not Music’s only problem as anyone switching from iTunes to Music will know.

Suggestions welcome.

It might be a memory issue with getting that many tracks at once.
I made a more complex script that will get the tracks 2000 at a time.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

property albArts : {}
property sortAlbArts : {}
property Albs : {}
property SortAlbs : {}
property locations : {}
property trackNames : {}
property trackIDs : {}

on run
	local sdt, edt, fileTracks, aTrack, flag, ct, cstr, dur, alist, remainder
	set flag to true
	if flag then
		set progress description to "Getting Music Tracks…"
		set progress additional description to "(0)"
		set progress total steps to -1
	end if
	set sdt to current date
	tell application "Music"
		set currPL to playlist "Library"
		set ct to count (file tracks in currPL whose kind is not "Internet audio stream")
		set remainder to ct mod 1000
		repeat with i from 1 to ct div 1000
			set {end of trackIDs, end of trackNames, end of albArts, end of sortAlbArts, end of Albs, end of SortAlbs, end of locations} to {id, name, album artist, sort album artist, album, sort album, location} of tracks ((i - 1) * 1000 + 1) thru (i * 1000) in currPL
			set my progress additional description to "(" & (i * 1000) & ")"
		end repeat
		if remainder > 0 then
			set {end of trackIDs, end of trackNames, end of albArts, end of sortAlbArts, end of Albs, end of SortAlbs, end of locations} to {id, name, album artist, sort album artist, album, sort album, location} of tracks (i * 1000) thru (i * 1000 + remainder) in currPL
		end if
	end tell
	-- flatten lists albArts,sortAlbArts,Albs,SortAlbs,locations
	repeat with alist in {a reference to trackIDs, a reference to trackNames, a reference to albArts, a reference to sortAlbArts, a reference to Albs, a reference to SortAlbs, a reference to locations}
		set alist to contents of alist
		set tmp to {}
		repeat with i from 1 to count (contents of alist as list)
			set tmp to tmp & item i of alist
		end repeat
		set contents of alist to tmp
	end repeat
	
	set cstr to " of " & ct & " - "
	repeat with i from 1 to ct
		if (i mod 100) = 0 then
			set dur to ((current date) - sdt) as integer
			set my progress additional description to "\"" & (item i of trackNames) & "\" - ID:" & (item i of trackIDs) & ", index " & i & cstr & my convertToHMS(dur) & ", eta - " & my convertToHMS((dur / i * (ct - i)) as integer)
		end if
	end repeat
	convertToHMS(((current date) - sdt) as integer)
end run

on convertToHMS(n)
	local dds, hhs, mns, secs
	set dds to n div 86400
	set n to n mod 86400
	set hhs to n div 3600
	set n to n mod 3600
	set mns to n div 60
	set secs to n mod 60
	return (item (((dds > 0) as integer) + 1) of {"", (dds as text) & ":"}) & (text -2 thru -1 of ("0" & hhs)) & ":" & (text -2 thru -1 of ("0" & mns)) & ":" & (text -2 thru -1 of ("0" & secs))
end convertToHMS

Only one problem. This script will error out when it hit a track that is an “Internet audio stream”. They don’t have a location property.

So instead, here’s a version that get all the properties of the tracks for later parsing.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

property trackNames : {}

on run
	local sdt, edt, fileTracks, aTrack, flag, ct, cstr, dur, alist, remainder
	set flag to true
	if flag then
		set progress description to "Getting Music Tracks…"
		set progress additional description to "(0)"
		set progress total steps to -1
	end if
	set sdt to current date
	tell application "Music"
		set currPL to playlist "Library"
		set ct to count (file tracks in currPL)
		set remainder to ct mod 1000
		repeat with i from 1 to ct div 1000
			set trackNames to trackNames & properties of tracks ((i - 1) * 1000 + 1) thru (i * 1000) in currPL
			set my progress additional description to "(" & (i * 1000) & ")"
		end repeat
		if remainder > 0 then
			set trackNames to trackNames & properties of tracks (i * 1000) thru (i * 1000 + remainder) in currPL
		end if
	end tell
	
	set cstr to " of " & ct & " - "
	repeat with i from 1 to ct
		if (i mod 100) = 0 then
			set dur to ((current date) - sdt) as integer
			set my progress additional description to "\"" & (name of item i of trackNames) & "\" - ID:" & (id of item i of trackNames) & ", index " & i & cstr & my convertToHMS(dur) & ", eta - " & my convertToHMS((dur / i * (ct - i)) as integer)
			delay 1
		end if
	end repeat
	convertToHMS(((current date) - sdt) as integer)
end run

on convertToHMS(n)
	local dds, hhs, mns, secs
	set dds to n div 86400
	set n to n mod 86400
	set hhs to n div 3600
	set n to n mod 3600
	set mns to n div 60
	set secs to n mod 60
	return (item (((dds > 0) as integer) + 1) of {"", (dds as text) & ":"}) & (text -2 thru -1 of ("0" & hhs)) & ":" & (text -2 thru -1 of ("0" & mns)) & ":" & (text -2 thru -1 of ("0" & secs))
end convertToHMS

Thanks for that extensive reply. Since it has worked a few times now and I’ve managed to do what I currently need, I’ll put it on the back burner until it starts misbehaving again.

It had occurred to me that memory was the problem, but there’s no reason for it to be and as I said, iTunes ran it perfectly for years on this exact same Mac Pro with NEVER a problem. So whatever it is, it’s been introduced by Music which quite frankly appears to have been given to Apple’s teenage tea boy as a project on which to practice and learn about programming.

The issue of streaming ‘tracks’ is something I’ve struggled with. At one time (iTunes I suspect) their ‘kind’ was set to “Internet audio stream”, but that is no longer necessarily the case. The stations I have saved are inconsistent, with some having their ‘kind’ set as above, but others just blank, so no good to use to select or filter those entries - as I discovered when my Radio station playlist went haywire.

Music displays “Continuous” for ‘Time’ and “Stream” for ‘Size’, but the latter cannot be used to filter as smart playlist rules only allow a small number. However, ‘Time’ is a little more flexible and smart playlist rules will allow a big number to be entered (so way longer than any track could possibly be) and setting the rule to ‘Time’ greater than that large number will effectively then only include streams.

It works, but is a kludge, unfortunately required since Apple provide NO way to otherwise filter streams.

I then set ‘grouping’ of everything in that smart playlist to “radio” and use that to filter in other places as it is then a more ‘absolute’ criteria and is what I use to filter tracks when loading from the playlist as in the subject of this thread to make sure the music tracks list is not polluted by radio streams which in any case would be meaningless if exported.

I also made a version that gets the tracks 1000 at a time, that doesn’t need a flatten operation.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

property albArts : {}
property sortAlbArts : {}
property Albs : {}
property SortAlbs : {}
property locations : {}
property trackNames : {}
property trackIDs : {}
property tracksList : {}

on run
	local sdt, edt, fileTracks, aTrack, flag, ct, cstr, dur, alist, rn, lc, cc
	set lc to 1000 -- loop count of tracks to get each iteration
	set sdt to current date
	tell application "Music"
		set currPL to playlist "Library"
		set ct to count (file tracks in currPL)
		set my progress description to "Getting iTunes Tracks…"
		set my progress additional description to ("0 of " & ct & " in playlist \"" & (name of currPL) & "\"")
		set my progress total steps to (ct div lc)
		set rn to lc --ct mod lc
		set cc to ct div lc
		set cstr to " in playlist \"" & (name of currPL) & "\", eta - "
		repeat with i from 1 to cc + 1
			if i > cc then
				set rn to ct mod lc -- remainder
				if rn = 0 then exit repeat
			end if
			set k to (i - 1) * lc
			set my tracksList to properties of file tracks (k + 1) thru (k + rn) in currPL
			repeat with j from 1 to rn
				try -- will error if file does not have a location
					set {end of trackNames, end of trackIDs, end of albArts, end of sortAlbArts, end of Albs, end of SortAlbs, end of locations} to {name, id, album artist, sort album artist, album, sort album, location} of item j of my tracksList
				end try
			end repeat
			tell me to set dur to ((current date) - sdt) as integer
			set my progress completed steps to i
			set my progress additional description to ((k + rn) & " of " & ct & cstr & my convertToHMS((dur / (k + rn) * (ct - (k + rn))) as integer)) as text
		end repeat
	end tell
	set ct to count my trackIDs
	set cstr to " of " & ct & " - "
	set my progress completed steps to 0
	set my progress total steps to (ct div 10)
	set edt to current date
	repeat with i from 1 to ct -- this will loop thru complete list for you to do something with the tracks
		if (i mod 10) = 0 then
			set dur to ((current date) - edt) as integer
			set my progress additional description to "index " & i & cstr & my convertToHMS(dur) & ", eta - " & my convertToHMS((dur / i * (ct - i)) as integer) & ", ID:" & (item i of my trackIDs) & " - \"" & (item i of my trackNames) & "\""
			set my progress completed steps to (i div 10)
			delay 0.3
		end if
	end repeat
	convertToHMS(((current date) - sdt) as integer)
end run

on convertToHMS(n)
	local dds, hhs, mns, secs
	set dds to n div 86400
	set n to n mod 86400
	set hhs to n div 3600
	set n to n mod 3600
	set mns to n div 60
	set secs to n mod 60
	return (item (((dds > 0) as integer) + 1) of {"", (dds as text) & ":"}) & (text -2 thru -1 of ("0" & hhs)) & ":" & (text -2 thru -1 of ("0" & mns)) & ":" & (text -2 thru -1 of ("0" & secs))
end convertToHMS

** EDIT ** fixed a few bugs
** EDIT2 ** more clean-up of code and progress bar

It ran fine for a couple of days, but today it fails EVERY time. Simply cannot get it to complete the playlist load.

Making matters worse is that an early part of the script checks the ‘name’ and ‘special kind’ of the selected playlist as it operates differently if the main music library is selected.

I just discovered today that although when run in Script Editor, it gets the ‘name’ and ‘special kind’ correctly (“Music” and “Music”), when I try to run it from the main script menu (i.e. not Music’s own script menu), it returns the ‘special kind’ as:-

**«constant **kSpZ»

So running from the script menu and from within Script Editor produces different results from the exact same script code, with Music in the exact same state.

I cannot overstate my disappointment and indeed horror at the chronic state of Apple’s current programming ability. I have never come across such unreliable and generally flaky software, even when having to deal with Windows. How have Apple managed to produce such a shoddy product as Music. Astounding.

That aside, any further thoughts on all this would be appreciated,

Are you referring to my script or your script that you modified?

If it is your script, please post it.

My script. The line that builds the big list has not changed, but the earlier part that checked what playlist is selected is as follows:-

# first check if suitable playlist is selected
tell application "Music"
	copy (a reference to (get view of front window)) to currPL
	set {currPlName, cPLSK} to {name, special kind} of currPL
	set isMuLib to cPLSK as text is "Music"
end tell

if isMuLib or characters -4 thru -1 of currPlName as text is equal to "Sync" then
	dLOG("Good playlist selected: " & currPlName)
else
	err("Unsuitable playlist selected: " & currPlName)
	return
end if

When one of the main ‘playlists’ is selected and script is run in Script Editor, it ALWAYS logs “Good playlist etc.”, but if run from the main script menu, it ALWAYS logs “Unsuitable etc.” because the ‘special kind’ is returned as garbage.

So same target app (Music), same state, nothing changed, but different ways to execute the script generate different results.

I am reworking the script anyway and will use a playlist of my own rather than one of the main ones as that might have benefits with the first problem of timing out. So I will no longer need to check the ‘special kind’, but that doesn’t excuse Apple’s failure.

The reason it gets garbage is you are trying to convert cPLSK to text outside of the "Tell application “Music”’ block

i edited the tell block below

tell application "Music"
	set currPL to view of front window
	set currPlName to name of currPL
	set cPLSK to special kind of currPL as text -- convert to text here inside tell block
end tell
set isMuLib to cPLSK is "Music" -- this can be executed outside the tell block

** EDIT ** might still be bad, hold on… CRAP! still giving garbage!

Hold on, I think it’s a permissions issue

Try this

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

tell application "Music"
	set currPL to view of front window
	set currPlName to name of currPL
	set isMuLib to currPlName is in (name of playlists whose special kind is Music)
end tell

if isMuLib or characters -4 thru -1 of currPlName as text is equal to "Sync" then
	display alert ("Good playlist selected: " & currPlName)
else
	display alert ("Unsuitable playlist selected: " & currPlName)
	return
end if

As I said I have implemented a different playlist and selection check so this problem no longer arises.

However, my complaint about Apple is not so much that it returns garbage outside the tell block, but that the entire AppleScript eco system produces a different result if run in Script Editor compared to running from the Script menu.

I can always sort out issues like what I was getting, but whatever I was, or was not doing, those 2 methods of execution should return the same result.

Whatever you may think, the Music app is like a poor beta. Things that ran fine in iTunes now failing in Music due to AppleEvent timeout errors, different results due to different execution methods, not to mention the TOTAL inability in Monterey to import an iTunes library (doesn’t even try) and continued inability to find almost any artwork. Again, things that worked in iTunes and even in Catalina Music.app, simply failing.

I fully support Apple’s decision to split up iTunes, this is not an ‘I love iTunes’ rant. My (and MANY others) problem is the quality of Music.app. It even fails to update the screen half the time. Did I say Beta? More like an Alpha release.

My coding is not perfect and I can make mistakes, but it’s just something I do in my spare time. I’m not a trillion dollar company (the richest on the planet) who absolutely should do better.

Still having a problem with the playlist loading script that was the original subject of this topic.

I was trying to load 20k+ tracks to then work through them all. To ensure that list did not contain any Internet radio stations, I used a 'whose grouping is not “radio” to filter them out. Nothing wrong with the syntax as it ran perfectly in iTunes and also with smaller numbers in Music.

In order to simplify the playlist loading command, I created a new playlist that excluded those ‘streams’ and use that as the source playlist, so I modified the script to remove the ‘whose etc’ filter. Even with 20k tracks it then ran fine. Several times. Over several days. So it looked like the ‘whose…’ filter was the problem in Music.app.

Then the other day I tried to run it again and was dismayed that it failed again, same problem. I tried repeatedly all day, quitting Music in between, either because it remained hung or just for it to be ‘fresh’. However, no matter what I tried, it fails with the timeout and Music is hung. (“not responding”) for a long while or permanently. I have been unable to run the script.

This is beyond aggravating. A script that ran 100% in iTunes now has this single line that Music will randomly get stuck on. I’ve surmounted all other ‘gotchas’ Music has thrown at me, but this has me stumped.

I have ascertained that it is ‘location’ causing the problem. The following works every time:-

tell application "Music"
	copy (a reference to (get view of front window)) to currPL
	set {albArts, sortAlbArts, Albs, SortAlbs, IDs} to {album artist, sort album artist, album, sort album, id} of file tracks in currPL
end tell

However:-

tell application "Music"
copy (a reference to (get view of front window)) to currPL
set locations to location of file tracks in currPL
end tell

fails, every time. So for whatever reason, Music is unable to get the locations of all the tracks in this playlist. In fact, it hangs. Seems as if there is a problem with one or more track’s locations causing Music to hang.

If that’s the case, then if I could figure which tracks are causing the issue, I might be able to fix it. Just not sure how to find out which it is.

I was hoping to try loading the POSIX path instead, but cannot find a way to do that directly.

I can see that it gets the first 4 properties for 20k tracks in about a second, then it’s getting all the ‘locations’ that takes a long time and often an AppleEvent timeout.

However, while testing out various options, I found that after changing the sorting of the playlist from Album to Album by Artist, it ran fine and got everything it needed from the big playlist.

So getting ‘locations’ is what has been causing the problem, but now the playlist is sorted differently, even ‘locations’ are not causing problems and the whole process of loading the playlist takes 9 seconds.

I have noticed before that when it is failing and I start testing with smaller playlists, I suddenly find that even the big one starts working. However, it will then fail again on another day. So is it the testing process that gets it running ok, or is it simply the different sort order. The latter seems to fit my experience as it is quite likely that for other reasons I have been changing that in between trying to run this script.

All I can do is ensure it is sorted Album by Artist before running it and see if that solves the problem or whether it re-occurs.

I’ve had to re-write how the script ‘selects’ the other smaller playlists it requires. I was using the ‘Loved’ attribute and simply working through those, until I discovered that Music simply forgets that attribute when it quits and also at other times. So it’s a waste of time trying to set and use that as next time you need it, Music will have forgotten.

Music.app was released 6 years ago and it’s still abysmal.

iTunesLibrary.framework gives us high-speed access.
Getting titles from 8.5K tracks took only 1.2 seconds with 10 years old MacBook Pro 2012.

http://piyocast.com/as/archives/4061

And this book contains such a useful scripts.

1 Like

Why this COPY A REFERENCE…? Try to tell to objects directly:

tell application "Music" to ¬
	tell view of window "Music" to ¬
		tell file tracks to ¬
			set {albArts, sortAlbArts, Albs, SortAlbs, IDs} to ¬
				{location, album artist, sort album artist, album, sort album, id}

.
Also, do to not use syntax FILE TRACKS IN…, because IN keyword is designed for AppleScript LISTS and not for Music.app PLAYLIST OBJECT.

Turn off the DEBUG mode if you are running the script in the Script Debugger. There may be a memory overflow or a computer load with many tasks as well.

Thanks for following it up, but none of the early lines are causing the problem. Not sure where I got the ‘reference to’ stuff from. DougScripts I think. I can easily change that, but is there any actual/real advantage to telling objects directly in the way that you suggest? Surely it’s just different ways of writing the same thing?

In any case, none of it is the problem. However I get the playlist (currPL),

tell application "Music" to set newList to album of file tracks in currPL

will ALWAYS succeed. 100%. Same as if I get artist, album artist etc. But if I try to get location, it will probably fail. However I can find no consistency to why it may fail or it may succeed.

The problem is ONLY to do with getting the location property and the exact same code was NEVER a problem in Mojave iTunes, but usually is in Monterey Music.

Dare I say that the problem is not in the actual script, but something in Monterey and/or Music.app is screwed up and can cause it to fail to get thousands of locations. A few hundred will always work. A few thousand will probably work, but many thousands will probably fail. Same code every time. This is a fault in Apple’s product(s) somewhere.

Unless someone can make that line above actually retrieve a list of 20k+ locations, reliably, every time, without fail, then I remain convinced it is Apple’s poor development, which let’s face is it has shown to be dire with respect to Music.app.

To further test, I instead grabbed a list of ids from the 20k playlist and then iterated through that list getting the other properties I need, including location. By the time it was half way through it was running so slowly I could count each track and finally it simply ground to a halt and I had to stop the script running. It was writing the output to a file and I could watch as the tracks (text) were written to the file and it simply stopped being written to. Music was incapable of handling many thousands of AppleEvents to get the properties. Hence the reason why I originally wrote it to grab them all in one hit (actually I think it’s one AE for each property, but that means only 5 as opposed to over 20k).

Again, I’d been interested to hear any justifiable reasons why a scripting system like AppleScript simply stuffs up when used to any decent extent. As is usually the case with Apple it would appear, they write stuff to be used with half a dozen or so items. Any more than that is a bit too complicated and shouldn’t be expected to work.

Funnily enough, the exception really was iTunes which I found worked fine with 26k tracks. Music struggles more with lags each time you switch the main playlist and sometimes just doesn’t draw the window, just a big blank and have to quit Music and start again. Shoddy programming. Amateurish. From the world’s richest company.

However, if anyone can justify what a poor job Apple has made of Music.app, I and the thousands of other appalled users would like to know.

Just to clarify, I am not an Apple hater. Have always loved their product and supported and recommended them. I’m just bitterly disappointed.

@UKenGB,

I don’t have 20k songs to test my script better. You didn’t say whether what you were offered works.

I have been testing with your suggestions, but slightly altered as I need currPL and currPlName later in the script. So testing with this:-

log ((current date) as string) & " - start"
tell  application "Music"
	set currPL to view of front window
	set currPlName to name of currPL
	log currPlName & " contains " & (count file tracks of currPL) & " tracks"
	tell currPL to ¬
		tell file tracks to set {IDs, albArts, sortAlbArts, Albs, SortAlbs, locations} to {id, album artist, sort album artist, album, sort album, location}
end tell
log "list of " & (count of IDs) & " tracks"
log ((current date) as string) & " - end"

This has not failed for several runs. However, the previous version that uses ’ FILE TRACKS IN’ is also currently working. This is the problem. It may work or it may fail. It was working with my original script earlier today, then after many runs it failed. Then it worked again and now running your method is working, but I have no confidence it will next time I need it.

I will make the same changes in the main script and just have to see if it continues to work, although I’m not holding my breath just because it has proven to be so inconsistent and whatever the issues with using ’ FILE TRACKS IN’ (I seem to recall I originally got that from this forum as a way to avoid too many AEs getting bogged down), as I keep saying, it worked 100% in iTunes. Whatever the problems, they did NOT exist in iTunes and since there should not be this discrepancy, I’d say that ultimately it’s down to Apple, even if I/we are able to find a way around it.

I edited my script that gets the list 1000 at a time.
Take a look at the try block (it will get the location if it can)
I also moved as much code out of the 'tell application “Music” ’ block as possible

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

property albArts : {}
property sortAlbArts : {}
property Albs : {}
property SortAlbs : {}
property locations : {}
property trackNames : {}
property trackIDs : {}
property tracksList : {}

on run
	local sdt, edt, fileTracks, aTrack, flag, ct, cstr, dur, alist, rn, lc, cc
	set lc to 1000 -- loop count of tracks to get each iteration
	set sdt to current date
	set currPL to "Library"
	tell application "Music" to set ct to count (file tracks in playlist currPL)
	set progress description to "Getting iTunes Tracks…"
	set progress additional description to ("0 of " & ct & " in playlist \"" & (currPL) & "\"")
	set progress total steps to (ct div lc)
	set rn to lc --ct mod lc
	set cc to ct div lc
	set cstr to " in playlist \"" & currPL & "\", eta - "
	repeat with i from 1 to cc + 1
		if i > cc then
			set rn to ct mod lc -- remainder
			if rn = 0 then exit repeat
		end if
		set k to (i - 1) * lc
		tell application "Music" to set my tracksList to properties of file tracks (k + 1) thru (k + rn) in playlist currPL
		repeat with j from 1 to rn
			using terms from application "Music"
				set {end of trackNames, end of trackIDs, end of albArts, end of sortAlbArts, end of Albs, end of SortAlbs} to {name, id, album artist, sort album artist, album, sort album} of item j of my tracksList
			end using terms from
			try -- will error if file does not have a location
				set end of locations to location of item j of my tracksList
			on error
				set end of locations to ""
			end try
		end repeat
		
		set dur to ((current date) - sdt) as integer
		set progress completed steps to i
		set progress additional description to ((k + rn) & " of " & ct & cstr & my convertToHMS((dur / (k + rn) * (ct - (k + rn))) as integer)) as text
	end repeat
	set ct to count my trackIDs
	set cstr to " of " & ct & " - "
	set cc to 15 -- number of songs per loop
	set progress completed steps to 0
	set progress total steps to (ct div cc)
	set edt to current date
	repeat with i from 1 to ct -- this will loop thru complete list for you to do something with the tracks
		if (i mod cc) = 0 then
			set dur to ((current date) - edt) as integer
			set progress additional description to "index " & i & cstr & my convertToHMS(dur) & ", eta - " & my convertToHMS((dur / i * (ct - i)) as integer) & ", ID:" & (item i of my trackIDs) & " - \"" & (item i of my trackNames) & "\""
			set progress completed steps to (i div cc)
			delay 0.3
		end if
	end repeat
	convertToHMS(((current date) - sdt) as integer)
end run

on convertToHMS(n)
	local dds, hhs, mns, secs
	set dds to n div 86400
	set n to n mod 86400
	set hhs to n div 3600
	set n to n mod 3600
	set mns to n div 60
	set secs to n mod 60
	return (item (((dds > 0) as integer) + 1) of {"", (dds as text) & ":"}) & (text -2 thru -1 of ("0" & hhs)) & ":" & (text -2 thru -1 of ("0" & mns)) & ":" & (text -2 thru -1 of ("0" & secs))
end convertToHMS