View Full Version : Applescript and iTunes Help!
bduff9
Sep 6, 2007, 02:36 PM
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
Sep 6, 2007, 03:02 PM
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
Sep 7, 2007, 05:48 PM
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
Sep 7, 2007, 08:31 PM
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
Sep 7, 2007, 10:02 PM
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:
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
Sep 7, 2007, 10:35 PM
I'm sorry, this is the actual, simplified checker:
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
vBulletin® v3.8.6, Copyright ©2000-2012, Jelsoft Enterprises Ltd.