Applescript and iTunes Help!

Discussion in 'Mac Programming' started by bduff9, Sep 6, 2007.

  1. bduff9 macrumors newbie

    Joined:
    Sep 6, 2007
    #1
    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
     
  2. MongoTheGeek macrumors 68040

    MongoTheGeek

    Joined:
    Sep 13, 2003
    Location:
    Its not so much where you are as when you are.
    #2
    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.
     
  3. bduff9 thread starter macrumors newbie

    Joined:
    Sep 6, 2007
    #3
    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
     
  4. MongoTheGeek macrumors 68040

    MongoTheGeek

    Joined:
    Sep 13, 2003
    Location:
    Its not so much where you are as when you are.
    #4
    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.
     
  5. bduff9 thread starter macrumors newbie

    Joined:
    Sep 6, 2007
    #5
    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
     
  6. bduff9 thread starter macrumors newbie

    Joined:
    Sep 6, 2007
    #6
    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
     

Share This Page