Home of the Squeezebox™ & Transporter® network music players.
Results 1 to 3 of 3
  1. #1

    iTunes playlist script

    I manage my music & playlists on my laptop, but have a shadow music storage on a NAS at home and run slimserver from a home server (been both windows box and linux box from time to time) pointed to the NAS. With this setup, the built in iTunes playlist usage in slimserver doesn't help (as my local iTunes Library.xml file is on my laptop).

    I tried a few iTunes playlist export utilities, but none fixed the fact that the path (and if I was using the linux box for slimserver, forward slash vs. backslash in the paths) is different between my iTunes Library.xml and where slimserver expects to see files on the NAS. This left me doing a series of editpad search and replaces every time. Which not surprisingly meant I didn't update the slimserver playlists very often.

    Recently, I wrote a PowerShell (formerly know as Monad) script that will parse the iTunes Library.xml, make the necessary path conversions, output extended m3u playlists to my NAS playlist directory, and force a slimserver rescan.

    In the case anybody else out there would find something like this helpful here is the script. Just fill in the right paths, etc. in the Variable Setup section and it should work fine. FWIW, it takes about 55 seconds to complete the conversion of my 6000 song, 100 playlist iTunes Library on my Core 2 Duo laptop. Its been 10 years since I wrote any code so excuse any inefficiencies that may offend a pro.

    --------Powershell Script---------------------------

    ################################################## ########################
    # Key Variable Setup
    ################################################## ########################

    $itunesxml = "C:\XXXX\XXXXXX\Music\iTunes\iTunes Music Library.xml"
    $plloc = "X:\PLAYLISTFOLDER\"
    $oldpath = "file://localhost/X:/"
    $newpath = "\\SERVER\Music\"
    $olddirsep = "/"
    $newdirsep = "\"
    $blocklist = "Library", "Movies", "Music", "Party Shuffle", "Podcasts", "Purchased", "TV Shows"
    $rescan = "http://XXX.XXX.XXX.XXX:9000/status.html?p0=rescan;cauth=XXXXXXXXXXXXXXXXXXXX"

    ################################################## ########################
    # Export Playlists & Rescan Slimserver Library
    ################################################## ########################

    $playlisttrigger = $false
    $newstr="#EXTM3U"
    $starttime=$(get-date)
    echo "" "Parsing Library . . . " ""
    gc $itunesxml | % {
    if (-not $playlisttrigger) {
    Switch -regex ($_) {
    '(<key>Track ID<.key><integer>)([0-9]*)(<.integer>)' {
    $idtemp=$matches[2]
    $nametemp = "NAMEERROR"
    $timetemp = [int] -1
    $loctemp = "LOCATIONERROR"
    }
    '(<key>Name<.key><string>)(.*)(<.string>)' {$nametemp=$matches[2]}
    '(<key>Total Time<.key><integer>)([0-9]*)(<.integer>)' {$timetemp=[int]($matches[2]/1000)}
    '(<key>Location<.key><string>)(.*)(<.string>)' {
    $loctemp=$matches[2]
    $tracktable += @{"$idtemp" = @{ "name" = $nametemp; "playtime" = $timetemp; "location" = $loctemp}}
    }
    '<key>Playlists<.key>' {
    $playlisttrigger=$true
    del "$plloc*.m3u"
    echo "Writing Playlists . . . " ""
    }
    }
    }
    else {
    Switch -regex ($_) {
    '(<key>Name<.key><string>)(.*)(<.string>)' {
    $skippl=$false
    foreach ($bltemp in $blocklist) {
    $bltemp = "^$bltemp"
    if ($matches[2] -match $bltemp) {
    $skippl=$true
    break
    }
    }
    if (-not $skippl) {
    if ($emt) {del temp.tmp}
    if (test-path temp.tmp) {Move-Item temp.tmp $newm3u}
    $newm3u=$plloc+$matches[2]+".m3u"
    Add-Content temp.tmp $newstr
    $emt=$true
    }
    }
    '(<key>Track ID<.key><integer>)([0-9]*)(<.integer>)' {
    if (-not $skippl) {
    $id=$matches[2]
    $newline="EXTINF:" + $tracktable[$id].playtime + ", " + $tracktable[$id].name
    Add-Content temp.tmp $newline
    $newline=$tracktable[$matches[2]].location
    $newline=$newline -replace $oldpath, $newpath
    $newline=$newline -replace $olddirsep, $newdirsep
    $newline=$newline -replace "%20", " "
    Add-Content temp.tmp $newline
    $emt=$false
    }
    }
    }
    }
    }
    if ($emt) {del temp.tmp}
    if (test-path temp.tmp) {Move-Item temp.tmp $newm3u}
    echo "Initiating Rescan of Slimserver . . . " ""
    $wc=New-Object net.webclient
    $page=$wc.DownloadString($rescan)
    $runtime=(New-TimeSpan $starttime $(get-date)).TotalMilliseconds/1000
    echo "Completed" "" "Script Run Time: $runtime seconds" "" "Press any key to exit"
    $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

    --------------End-----------------------------------

    PS. Not sure why this Forum collapsed the indenting in the script, as I know this makes it harder to read I am also posting a txt file that should retain the formating.
    Last edited by IPGuy; 2007-05-26 at 08:40.

  2. #2
    Junior Member
    Join Date
    Dec 2007
    Posts
    2

    Python solution

    This posting was very helpful to the same problem, but I decided to use Python to solve the issue. This was fairly easy and the xml parsing appear very fast with cElementTree.

    import time
    import datetime
    import os
    import string
    import xml.etree.cElementTree as ET
    import urllib

    ################################################## ########################
    # Variable Setup
    ################################################## ########################

    itunesxml = "C:\Documents and Settings\calvinh\My Documents\My Music\iTunes\iTunes Music Library.xml"
    #itunesxml = "C:\\test\\iTunes Music Library.xml"
    startM3U ="#CURTRACK 0\r\n#EXTM3U\r\n"
    startName = "#EXINF:-1,"
    plloc = "M:\\iTunes\\Playlist\\" #Windows mapped path
    oldpath = "file://localhost/M:/iTunes/iTunesMusic/" #iTunes mapped path
    newpath = "/ext/Qmultimedia/iTunes/iTunesMusic/" #NAS music location
    blocklist = "Library","Audiobooks", "Movies", "Music", "Party Shuffle", "Podcasts", "Purchased", "TV Shows"
    rescan = "http://192.168.1.99:9000/status.html?p0=rescan;cauth=c6249a38db11db959094f8 56e91d2f66"

    print "Current System Variables"
    print
    print "Local iTunes xml file =",itunesxml
    print "Mapped Playlist location =",plloc
    print "Local iTunes path =",oldpath
    print "New NAS path =",newpath
    print "Current Blocked Playlist =",blocklist
    print rescan
    print
    ################################################## ########################
    # Export Playlists & Rescan Slimserver Library
    ################################################## ########################

    starttime = datetime.datetime.now()
    print "Script Started @ ", starttime
    print "" "Parsing Local iTunes Library . . . " ""
    print

    # Parsing iTunes xml
    root = ET.parse(itunesxml).getroot()

    #get non-blocked Playlists and Tracks in array
    def getPlaylist():
    for playlist in root[0].find('array').findall('dict'):
    l = list(playlist)
    plInfo = dict(zip([t.text for t in l[::2]], [t.text for t in l[1::2]]))
    plName = plInfo.get('Name',0)
    plID = plInfo.get('Playlist ID',0)
    #check for blocked Playlist and empty directories
    if plName not in blocklist and playlist.find('array') is not None:
    plx = playlist.find('array').findall('dict')
    print plName + " ID =" + plID
    trackID = []
    if playlist.find('array') is not '':
    for tr in playlist.find('array').findall('dict'):
    l = list(tr)
    tracks = dict(zip([t.text for t in l[::2]], [t.text for t in l[1::2]]))
    trackID.append(tracks.get('Track ID',0))
    setTrackInfo(plName,trackID)

    #write track information to m3u file
    def setTrackInfo(fileName,trackID):
    trf = file(plloc+fileName+'.m3u','w')
    trf.write(startM3U)
    for trackList in root[0].find('dict').findall('dict'):
    l = list(trackList)
    trackInfo = dict(zip([t.text for t in l[::2]], [t.text for t in l[1::2]]))
    track = trackInfo.get('Track ID',0)
    trackLoc = trackInfo.get('Location',0)
    trackName = trackInfo.get('Name',0)
    if track in trackID:
    trackLoc = string.replace(trackLoc,oldpath,newpath)
    trackLoc = string.replace(trackLoc,'%20',' ')
    trf.write('#EXTINF:-1,'+trackName+'\r\n')
    trf.write(trackLoc+'\r\n')
    trf.close()
    #Get iTune playlist and write tracks to E3U file
    getPlaylist()
    #Send rescan to Slimserver
    urllib.urlopen(rescan).read()

    ################################################## ############################
    # End of Playlist script
    endtime = datetime.datetime.now()
    print
    print "Script Complete @ ", endtime
    print "Execution Time = ",endtime - starttime
    print
    ################################################## ############################

    See attached playlist.txt for proper python formatting
    Last edited by artv; 2007-12-12 at 22:08. Reason: formatting incorrect

  3. #3
    This thread is pretty old but it came up pretty high in my Google search results so I thought I'd add a little more info...

    I have been running Logitech Media Server for many years from Windows. Recently I moved all my music to a Synology NAS and was having trouble getting the Media Server to "see" my content on the box. So I installed Logitech Media Server on the Synology NAS itself (supported right out of the box with just a few clicks!). Everything was working great except for the fact that all my playlists were being held captive by iTunes in Windows.

    My solution was to download iTunes Export from here:

    http://www.ericdaugherty.com/dev/itunesexport/

    I grabbed the command line version so I could write a batch file to invoke it easily. Here's the contents of my command file:

    "C:\Program Files (x86)\Java\jre6\bin\java" -jar itunesexport.jar -outputDir=\\diskstation\Media\Music\iTunes\Playlis ts -musicPath=/volume1/Media/Music/iTunes/Music -musicPathOld=C:\Media\Music\iTunes\Music -fileTypes=ALL -separator=MAC -includePlaylist="Brad 4 Star Sorted,Brad 5 Star Sorted,Kids 4 Star"

    In the above command line the musicPathOld is where iTunes "sees" all my files from Windows, i.e. I created a softlink at C:\Media that points to \\diskstation\Media. The musicPath is the path that gets inserted into the m3u files, which is where Logitech Media Server "sees" the music locally on the NAS. I only wanted to create a few playlists as indicated by the includePlaylist. If you get rid of that part it generates all the playlists. I also have my iTunes library xml in the default location so didn't need to specify anything there.

    Anyway, I hope this helps someone else having a similar issue. Now if I want to re-create the m3u files I simply run the batch file and then rescan playlists.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •