Mac Applescript and iTunes Help!

bduff9

macrumors newbie
Original poster
Sep 6, 2007
6
0
I am trying to order a playlist by certain restrictions. I have already written the code to check if a certain playlist does in fact follow these guidelines, but would like to write a program to order a playlist a certain way, then check it, order it a different way, check it, etc. until all possible orders have been used or it finds an order that fits my set rules. I absolutely cannot figure out how to write code for something like this since I want it general to apply to any playlist, so first I have to have an undetermined number of songs ordered, but also, how do I get it to go through every possible combination? Thanks in advance, I've been going crazy with this.

Duffey
 

MongoTheGeek

macrumors 68040
I am trying to order a playlist by certain restrictions. I have already written the code to check if a certain playlist does in fact follow these guidelines, but would like to write a program to order a playlist a certain way, then check it, order it a different way, check it, etc. until all possible orders have been used or it finds an order that fits my set rules. I absolutely cannot figure out how to write code for something like this since I want it general to apply to any playlist, so first I have to have an undetermined number of songs ordered, but also, how do I get it to go through every possible combination? Thanks in advance, I've been going crazy with this.

Duffey
How restrictive are the rules? Are you likely to get something valid randomly? If so you can just set the shuffle of the playlist to true then validate. If not it may make sense to build the list in a valid order.
 

bduff9

macrumors newbie
Original poster
Sep 6, 2007
6
0
They are not extremely restrictive, as in for any single restriction there are probably at least 60 songs that would work, but I am trying to restrict it further by only using songs I chose, as in newer or popular songs, versus every song in my library. Here's my original thought, which I deemed to complex at first but maybe someone can help me out with it.

Saying that I have a playlist of all the songs I wanna use, called "Good Songs" for instance, with maybe 5 hours worth, 72 different songs. Thats not that important though, as I want it to be flexible. Anyway, I want it to go in order start with song one, copy it to the new playlist "Good Songs Ordered", find the possible songs using my restrictions, copy track one from that list to the new playlist, and so on. If it runs into 0 songs able to be chosen but has not used every song, it will then go back one or two steps, only enough to try a different path, so instead of song one, it will use song two, and then continue on. If it uses every possible path with track one as a start, it will then erase it and start with track two in "Good Songs Ordered". I want it to repeat this until it either finds a correct sequence, or has gone through every choice. I know this could take a while so there would have to be breaks, but this is what I ideally need. I already have a selector script as well as a checker script to make sure a playlist follows my rules. I would basically just need the code to order the songs in sequence, but able to accommodate any number of tracks, since there might be 20, or there might be 40, or any number. I can post my previous scripts if that will help, but I definitely need help with this. Thanks.

Duffey
 

MongoTheGeek

macrumors 68040
Code:
property songlist : {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 4, 5, 6, 7, 6, 5, 4, 3, 3, 3, 2, 2, 1} --get every song of playlist yadayadayada
property outlist : {}
property lastItem : ""

on PlaceSongs(aList)
	if (count aList) = 1 then
		if canGoNext(item 1 of aList) then
			return aList
		else
			return {}
		end if
	else
		repeat with i from 1 to count aList
			if canGoNext(item i of aList) then
				set lastItem to item i of aList
				set sublist to PlaceSongs(sublist(aList, i))
				if sublist ≠ {} then return {} & item i of aList & sublist
			end if
		end repeat
		return {}
	end if
end PlaceSongs

on sublist(aList, i)
	if (count aList) = 1 then return {} -- shouldn't happen
	if i = 1 then return items 2 through -1 of aList
	if i = (count aList) then return items 1 through -2 of aList
	return {} & (items 1 through (i - 1) of aList) & (items (i + 1) through -1 of aList)
end sublist

on canGoNext(anItem)
	return anItem ≠ lastItem
end canGoNext
Be warned that this will run in N! time. For lots of songs it may take longer to run that it did to write.

You will need to populate Songlist and put in your own canGoNext routine.
 

bduff9

macrumors newbie
Original poster
Sep 6, 2007
6
0
Thanks a bunch. This seems like what I need. However, being a newbie to this, I cannot easily read what others have written for code. If you would be so kind, could you please explain it briefly, just the more advanced components, and possibly help me integrate my checker with it? Here is what I have written for the checker so you know where I am coming from:

Code:
global currplaylist, processtrack

tell application "iTunes"
	set processtrack to 2
	set currplaylist to name of current playlist
	set tracknum to count tracks of playlist currplaylist
	set shuffle of current playlist to false
	repeat with y from 1 to tracknum
		set shuffle of current playlist to false
		play track y of playlist currplaylist
		if y > 1 then
			set shuffle of current playlist to true
		end if
		set song repeat of current playlist to one
		set runcount to tracknum - 1
		set a to runcount - 1
		repeat while a > 0
			set runcount to runcount * a
			set a to a - 1
		end repeat
		repeat runcount times
			set z to 0
			if z > 0 then
				set shuffle of current playlist to true
			end if
			repeat until processtrack is equal to tracknum
				set trackcount to tracknum - 1
				repeat with x from 2 to trackcount
					my track_scan(x)
					if processtrack is 0 then
						set shuffle of current playlist to false
						set shuffle of current playlist to true
						set processtrack to 2
						exit repeat
					end if
				end repeat
				if processtrack is 2 then
					exit repeat
				end if
			end repeat
			if processtrack is equal to tracknum then
				exit repeat
			end if
			set z to z + 1
		end repeat
		if processtrack is equal to tracknum then
			exit repeat
		end if
	end repeat
	if processtrack is equal to tracknum then
		display dialog "Playlist " & currplaylist & " is ordered!"
	else
		display dialog "Playlist " & currplaylist & " is not ordered!"
		set shuffle of current playlist to false
	end if
end tell

on track_scan(x)
	tell application "iTunes"
		set prevtrack to (x - 1)
		set nexttrack to (x + 1)
		set prevbpm to bpm of track prevtrack of playlist currplaylist
		set nextbpm to bpm of track nexttrack of playlist currplaylist
		set currbpm to bpm of track x of playlist currplaylist
		set bpmrange to [currbpm - 10, currbpm - 9, currbpm - 8, currbpm - 7, currbpm - 6, currbpm - 5, currbpm - 4, currbpm - 3, currbpm - 2, currbpm - 1, currbpm, currbpm + 1, currbpm + 2, currbpm + 3, currbpm + 4, currbpm + 5, currbpm + 6, currbpm + 7, currbpm + 8, currbpm + 9, currbpm + 10, currbpm * 2, currbpm / 2]
		set currkey to comment of track x of playlist currplaylist
		set keyplaylist to "xDJ " & (currkey)
		if (get name of tracks of playlist keyplaylist) contains name of track prevtrack of playlist currplaylist then
			if (get name of tracks of playlist keyplaylist) contains name of track nexttrack of playlist currplaylist then
				if bpmrange contains prevbpm then
					if bpmrange contains nextbpm then
						set processtrack to processtrack + 1
					else
						my Failure()
					end if
				else
					my Failure()
				end if
			else
				my Failure()
			end if
		else
			my Failure()
		end if
	end tell
end track_scan

on Failure()
	tell application "iTunes"
		--display dialog "Playlist " & currplaylist & " is not ordered"
		set processtrack to 0
	end tell
end Failure
Thanks in advance!

Duffey
 

bduff9

macrumors newbie
Original poster
Sep 6, 2007
6
0
I'm sorry, this is the actual, simplified checker:

Code:
global currplaylist, processtrack

tell application "iTunes"
	set processtrack to 2
	set currplaylist to name of current playlist
	set tracknum to count tracks of playlist currplaylist
	set shuffle of current playlist to false
	set trackcount to tracknum - 1
	repeat with x from 2 to trackcount
		my track_scan(x)
		if processtrack is 0 then
			set processtrack to 2
			exit repeat
		end if
	end repeat
	if processtrack is equal to tracknum then
		display dialog "Playlist " & currplaylist & " is 100% ordered!"
	else
		set percentdone to processtrack / tracknum
		set percentdone to percentdone * 100
		display dialog "Playlist " & currplaylist & " is only " & percentdone & "% ordered!"
	end if
end tell

on track_scan(x)
	tell application "iTunes"
		set prevcheck to false
		set prevtrack to (x - 1)
		set nexttrack to (x + 1)
		set prevbpm to bpm of track prevtrack of playlist currplaylist
		set nextbpm to bpm of track nexttrack of playlist currplaylist
		set currbpm to bpm of track x of playlist currplaylist
		set bpmrange to [currbpm - 10, currbpm - 9, currbpm - 8, currbpm - 7, currbpm - 6, currbpm - 5, currbpm - 4, currbpm - 3, currbpm - 2, currbpm - 1, currbpm, currbpm + 1, currbpm + 2, currbpm + 3, currbpm + 4, currbpm + 5, currbpm + 6, currbpm + 7, currbpm + 8, currbpm + 9, currbpm + 10, currbpm * 2, currbpm / 2]
		set currkey to comment of track x of playlist currplaylist
		set keyplaylist to "xDJ " & (currkey)
		if (get name of tracks of playlist keyplaylist) contains name of track prevtrack of playlist currplaylist and bpmrange contains prevbpm then
			set processtrack to processtrack + 1
			set prevcheck to true
		end if
		if prevcheck is true then
			if (get name of tracks of playlist keyplaylist) contains name of track nexttrack of playlist currplaylist and bpmrange contains nextbpm then
				set processtrack to processtrack + 0
			else
				if (get name of tracks of playlist keyplaylist) contains name of track nexttrack of playlist currplaylist and bpmrange contains nextbpm then
					set processtrack to processtrack + 1
				end if
			end if
		end if
	end tell
end track_scan
Sorry for the confusion.

Duffey