View Single Post
  #2 (permalink)  
Old September 17th, 2007, 04:34 PM
minienigma minienigma is offline
Newbie Floating Down The Mistic River
 
Join Date: Sep 2007
Posts: 6
Not sure whether this will work for you, but...

I don't have a T30, I have a T60. When I was doing search for info on playlist format for the T60, I've noticed that the format seems to be different from T10 as well. After some investigation into it, I've written a script in python that generates playlists for the T60. You're welcome to give it a try. Please post reply about whether it works or not -- so that it may help future T30 users.

I've tried it on Mac OS X and Cygwin. Haven't had time to test on LINUX, yet.

The code is as follows:

Code:
#!/usr/bin/env python

# PLA.PY Generates playlist file from a list of files provided.
# Copyright (C) 2007  Lucas Lay
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys      # For command line arguments processing
import os       # For directory, filename, path processing
import struct   # For binary data output

def printhelp():
    sys.stderr.write('\nGenerate PLA/PLP song entries from specified music files.\n')
    sys.stderr.write('Usage: '+sys.argv[0]+' <-o output_file> [-r root_dir] <Music_file> [Music_file ... ]\n')
    sys.stderr.write( """
-r dir      Specify directory to be EXCLUDED from the M3U entries.
-o filename Specify output filename.
-h          Include PLA file header.

Note: model T30 may need playlist name, as a result must use -o option
to specify playlist name in order for playlist to work.
""")

def genPLAentries (filelist, rootdir):

    # Get rid of trailing directory slash for root directory
    if len (rootdir) > 1 and rootdir[-1] == u'/':
        rootdir = rootdir[:-1]

    PLAentries=[]
    for file in filelist:
        # If the root directory is part of the file path, we get rid of it
        if rootdir == file[:len(rootdir)]:
            file = file[len(rootdir):]

        # convert UNIX '/' to DOS '\'
        dosfile = file.replace(u'/',u'\\')

        if len(os.path.split(file)[0]) > 1:
            # Directory path length > 1 => file not in root directory. Add 2 for short position value
            # and extra trailing backslash
            PLAentries.append ({'namestart': len(os.path.split(file)[0]) + 2, 'filepath': dosfile})
        else:
            # Directory path length <= 1 means file in root directory. Add 1 for short position value only.
            PLAentries.append ({'namestart': len(os.path.split(file)[0]) + 1, 'filepath': dosfile})

    return PLAentries    

if __name__ == '__main__':
    if len (sys.argv) < 2:
        printhelp()
        sys.exit(1)

    i = 1    
    InsertHeader = False
    rootdir=''
    outputfilename = ''
    model='t60'

    # Get and parse command line arguments
    while i < len(sys.argv) and sys.argv[i][0] == '-':
        if sys.argv[i] == '-r':
            i = i + 1
            if os.path.exists(sys.argv[i]):
                rootdir = os.path.abspath(sys.argv[i]).decode('utf-8')
            else:
                sys.stderr.write( 'Error: directory "' + sys.argv[i] + '" not found!\n')
                sys.exit(1)

        elif sys.argv[i] == '-h':
            InsertHeader = True
            
        elif sys.argv[i] == '-o':
            i = i + 1
            outputfilename = sys.argv[i]

        else:
            sys.stderr.write( 'Error: Unknown option: "' + sys.argv[i] + '"\n')
            printhelp()
            sys.exit(1)
        
        i = i + 1        

    # if no more arguments left, then no song files ar provided
    if i >= len(sys.argv):
        sys.stderr.write('Error: No music file specified.\n')
        printhelp()
        sys.exit(1)

        
    filelist=[]

    # Go through the song list and check extension for supported files
    while i < len(sys.argv):
        # Get the file extension
        extension = os.path.splitext(sys.argv[i])[1]
        if os.path.exists(sys.argv[i]):
            # The path exists, check if it's file or directory.
            if os.path.isdir(sys.argv[i]):
                # Ignore the directory
                sys.stderr.write( 'Directory "'+sys.argv[i]+'" ignored.\n')

            # Add the file to file list if it has proper file extension.                
            elif extension == '.ogg' or \
               extension == '.mp3' or \
               extension == '.wav':
                filelist = filelist + [ os.path.abspath(sys.argv[i]).decode('utf-8') ]

            else:
                sys.stderr.write( os.path.split(sys.argv[i])[1] + \
                                  ': Ignored. Unsupported filetype ('+extension+').\n' )
        else:
            # Path does not exist, skip.
            sys.stderr.write( sys.argv[i]+': file does not exist... Ignored.\n')

        i = i + 1
 
    if len(rootdir) == 0:
        # If root directory of the player is not specified, we assume it's the current directory.
        rootdir=os.path.abspath('.').decode('utf-8')
        sys.stderr.write('No root directory specified. Assuming: %s\n' % rootdir.encode('utf-8'))
    
    if filelist != []:
        # Generate playlist entry.
        PLAentries = genPLAentries (filelist,rootdir)

        # If output file option not specified, we output to standard output.
        if outputfilename == '':
            outfile = sys.stdout
        else:
            outfile=open(outputfilename,'wb')

        # If insert header is specified, we output header first.        
        if InsertHeader:
            outstring = struct.pack('>L',len(PLAentries)) + 'iriver UMS PLA' + '\x00' * 30
            if outputfilename != '':
                outstring = outstring + os.path.splitext(os.path.split(outputfilename)[1])[0]
            outfile.write( outstring + '\x00' * (512 - len(outstring)) )
            
        # For each playlist entry, output the offset value then the file path in big endian utf-16.
        for entry in PLAentries:
            outstring=struct.pack('>H', entry['namestart']) + entry['filepath'].encode('utf-16-be')
            outfile.write( outstring + '\x00' * (512 - len(outstring)) )
 
    else:
        sys.stderr.write( 'No file processed.\n' )
Save into file, change execute permission, and run:

pla.py -h -r <path_to_device_root dir> -o <path_to_playlist> <path_to_song> [path_to_song] ...

For example, if your device is mounted on /Volumes/T30 (and using your file organization scheme) creating a playlist named MyPlayList with SongFileName1 and SongFileName2:

pla.py -h -r /Volumes/T30 -o /Volumes/T30/Playlists/MyPlayList.pla /Volumes/T30/DATA/ArtistName/AlbumName/SongFileName1 /Volumes/T30/DATA/ArtistName/AlbumName/SongFileName2
Let me know if this works... Good luck.

Last edited by minienigma : September 17th, 2007 at 06:44 PM.
Reply With Quote