Amarok/Archives/MediaDevicesIriverT10Script

From KDE Community Wiki

Playlist generator for Iriver T10 UMS

This is a simple python script that generates sorted playlists for the Iriver T10 mp3 player. It uses the filenames of the music files to sort the files.

It works fine on both win32 and Linux. But there is a problem with non-ASCII chars on Linux,
I get an error in the os.stat() function:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u253c' in position 1 1: ordinal not in range(128)

I'm still working on it, however.

#!/usr/bin/env python

"""
This is a program that generates sorted playlists for Iriver T10 UMS
Copyright (C) 2006 Dan Fritz

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
"""

import fnmatch, os, struct, sys

def uprint(msg):
    print msg.encode("latin1")

def toUni(msg):
    """
    Sometimes os.listdir(unicode) does not return unicode when it should.
    Instead it returns a mixture of byte strings and unicode - frustrating.
    This method tries to ensure that the string is converted to unicode
    """    
    if isinstance(msg,unicode):
        return msg
    else:
        try:
            return msg.decode("850")
        except:
            pass
        try:
            return msg.decode("latin1")
        except:
            throw  
    
def writePlaylists(root):
    """
    Recursively scans for music files under the directory "music"
    Creates sorted playlists of each folder with music found.
    """
    root=os.path.normpath(root)
    rootlen = os.path.join(root, u"music").find(u"music",len(root))
    playlists = walk(rootlen,os.path.join(root, u"music"), {})
    result = []
    
    for dir in playlists:
        playlistfn = os.path.join(root, u"Playlists")
        playlistname = os.path.basename(dir)+u".pla"
        playlistfn = os.path.join(playlistfn,os.path.basename(dir)+u".pla")
        uprint("Creating playlist \"%s\"" % (playlistname))
        f = open(playlistfn,"w")
        try:
            line = struct.pack(">l",len(playlists[dir]))
            line += "iriver UMS PLA"
            f.write(line)
            f.write("\0" * (512-len(line)))
            playlists[dir].sort()
            for file in playlists[dir]:
                file="\\" + file
                dirpathlen = len(os.path.dirname(file)) + 2
                file = file.replace("/","\\")
                uprint(" Added %s" % (file))

                line = struct.pack("xbx",dirpathlen)
                line += file.encode("utf-16")[2:]
                line += "\0" * (512-len(line))
                f.write(line)
        finally:
            f.close()
        uprint("Succesfully created playlist \"%s\"" % (playlistname))
    return result

def walk( rootlen, currdir, result):
    try:
        names = os.listdir(currdir)
    except os.error:
        return result

    pat_list = ["*.mp3","*.ogg","*.wma"]    
    for name in names:
        name = toUni(name)
        fullname = os.path.join(currdir, name)
        # grab if it matches our pattern and entry type
        for pat in pat_list:
            if fnmatch.fnmatch(name, pat):
                if os.path.isfile(fullname):
                    dirname = currdir[rootlen:]
                    if dirname not in result:
                        result[dirname]=[]
                    result[dirname].append(fullname[rootlen:])
                continue

        # recursively scan other folders, appending results
        if os.path.isdir(fullname) and not os.path.islink(fullname):
            walk(rootlen, fullname, result )

    return result

if __name__ == '__main__':
    "First argument to this script is the path to the Iriver mount"
    if len(sys.argv) > 1 :
        writePlaylists(sys.argv[1])
    else:
        writePlaylists('.')