Automatic iTunes Folder Playlist in Javascript and F#
The other day, I was struggling with my playlist on itunes. As you may know iTunes doesn’t have the notion of the folder structure of your mp3s. So if you do organise your music in folders you won’t have them in iTunes. I decided to write a script using the iTunes COM SDK for doing that.
Here is the scenario all the music is stored in d:\Music. So the script starts exploring everything inside in the folder and create an entry in iTunes, and it happens only in one level. First I did it with JavaScript with a lot of pain. I was pain because of the ugly interface and also unclear documentation. Luckily there were the samples in the SDK to play with it.
var iTunesApp = WScript.CreateObject("iTunes.Application"); var mainLibrary = iTunesApp.LibraryPlaylist; var mainLibrarySource = iTunesApp.LibrarySource; var tracks = mainLibrary.Tracks; var numTracks = tracks.Count; var numPlaylistsCreated = 0; var ITTrackKindFile = 1; var albumArray = new Array(); var playlists = mainLibrarySource.Playlists; for (var i = 1; i <= numTracks; i++) { var currTrack = tracks.Item(i); if (currTrack.Kind == ITTrackKindFile) { if (currTrack.Location != "") { var p =currTrack.Location var location = p if ((location != undefined) && (location != "")) { if (albumArray[location] == undefined) { albumArray[location] = new Array(); } albumArray[location].push(currTrack); } } } } WScript.Echo(" Tracks Read " + numTracks); for (var albumNameKey in albumArray) { var trackArray = albumArray[albumNameKey]; var p = albumNameKey; var ignoreFirst = p.indexOf("music\\",0); //3 var firstChar = 0; var secondChar = 0; var firstChar = ignoreFirst +5 ; var myArr = new Array(); while (true) { var firstChar = p.indexOf("\\", firstChar); var secondChar = p.indexOf("\\", firstChar+1); if (secondChar == -1 ) break; var newStr = p.substring(firstChar+1, secondChar) myArr.push(newStr); firstChar = secondChar; } var plist = null; if (myArr.length == 0) { if (playlists.ItemByName("_") != null) { plist = playlists.ItemByName("_") ; } else { plist = iTunesApp.CreatePlaylist("_"); numPlaylistsCreated++; } } else if ( playlists.ItemByName(myArr[0]) != null) { plist = playlists.ItemByName(myArr[0]) } else { plist = iTunesApp.CreatePlaylist( myArr[0]); numPlaylistsCreated++; } for (var trackIndex in trackArray) { var currTrack = trackArray[trackIndex]; plist.AddTrack(currTrack); } } //create playlist if (numPlaylistsCreated > 0) { WScript.Echo( numPlaylistsCreated + " (s) created."); } else { WScript.Echo("No playlist createds"); }
(It is written in a quick way without caring about the beauty
)
It was doing its job that I wanted but I also wanted to have my folder structure in itunes rather than a single entry for a folder. This time I implemented in F#. I have chosen F# mainly because of the type inference and the intellisense. In JavaScript without the documentation, you couldn’t do anything. F# is also chosen because of interoperability with COM and friends. So I have to admit that I didn’t like the COM interface of iTunes. All the best F# implementation with more functionality gave %40 less code
#light #r "Interop.iTunesLib.dll";; open iTunesLib; open System.IO; open System.Text.RegularExpressions let itunes = new iTunesLib.iTunesAppClass() let playLists = itunes.LibrarySource.Playlists let tracks = itunes.LibraryPlaylist.Tracks let track = tracks.Item(2) for track in tracks do if track.Kind = ITTrackKind.ITTrackKindFile && (track:?> IITFileOrCDTrack).Location <> null then let track = track :?> IITFileOrCDTrack let regex = new System.Text.RegularExpressions.Regex( @"^( ?<Drive>([a-zA-Z])):\\_music\\ ((?< directory>[\w\W]+)\\)*((?< playlist>[\w\W]+)\\)(?< filename>([\w\W]+.mp3))", RegexOptions.IgnoreCase) printf "%d\n" track.Index let resMatch = regex.Match(track.Location) if resMatch.Length = 0 () else let lastFolder = resMatch.Groups.Item("directory").Captures |> Seq.untyped_fold (fun (acc:IITPlaylist) (a: (System.Text.RegularExpressions.Capture)) -> match (playLists.ItemByName(a.Value)) with | null -> if acc.Index = 1 then itunes.CreateFolder(a.Value) else (acc :?> IITUserPlaylist).CreateFolder(a.Value) | a1 -> if (a1 :?> IITUserPlaylist).SpecialKind = ITUserPlaylistSpecialKind.ITUserPlaylistSpecialKindFolder then a1 else itunes.CreateFolder(a.Value) ) (playLists.Item(1) ) let pListName = resMatch.Groups.Item("playlist").Captures.Item(0).Value let lastPlayList= match (playLists.ItemByName(pListName)) with | null -> if lastFolder.Index = 1 then itunes.CreatePlaylist(pListName) :?> IITUserPlaylist else let fol = lastFolder :?> IITUserPlaylist fol.CreatePlaylist(pListName) :?> IITUserPlaylist | a2 -> if (a2 :?> IITUserPlaylist).SpecialKind = ITUserPlaylistSpecialKind.ITUserPlaylistSpecialKindFolder then match (playLists.ItemByName("_" + pListName)) with | null -> (a2:?> IITUserPlaylist).CreatePlaylist("_" + pListName) :?> IITUserPlaylist | a3 ->a3 :?> IITUserPlaylist else a2 :?> IITUserPlaylist lastPlayList.AddTrack(ref (track :> obj)) |> ignore done
The folder playlist is not implemented on iPod. Although it make sense to use in iTunes, there is no point doing it for iPod. I was a bit frustrated, it was my sole purpose. Anyway it was nice to play with it…
So I hope it will be helpful in a way, the folder playlist didn’t help me, maybe in the next firmware update… On the other hand, I still use the first implementation for my automatic one-level folder playlist.




Apple Ipod, Ipod Nano and Ipod Video News » Automatic iTunes Folder Playlist for Ipod using JavaScript and F#:
[…] Technology Evangelist - Technology News, Articles, Blogs, and Interviews wrote an interesting post today onHere’s a quick excerpt The other day, I was struggling with my playlist on itunes. As you may know iTunes doesn’t have the notion of the folder structure of your mp3s. So if you do organise your music in folders you won’t have them in iTunes. I decided to write a script using the iTunes COM SDK for doing that. Here is the scenario all the music is stored in d:Music. So the script starts exploring everything inside in the folder and create an entry in iTunes, and it happens only in one level. First I did it with Ja […]
6 January 2008, 5:22 amMovies and Film Blog » Automatic iTunes Folder Playlist for Ipod using JavaScript and F#:
[…] Can Erten | eh ooh, it’s a coding day! placed an interesting blog post on Automatic iTunes Folder Playlist for Ipod using JavaScript and F#Here’s a brief overview […]
7 January 2008, 7:15 amhario:
do you know of any way to execute that code in Firefox versus IE? If you switch WScript to create an ActiveXObject the application will run in IE, but what is the equivalent for FF?
18 February 2008, 7:59 pmCan:
First I don’t think that will be easy to switch to activexobject as well. But if you did, the similar in Firefox would be XPCOM
20 March 2008, 12:05 am