#!/usr/bin/python3 # This is a public domain file. # The code was written by Andrew Cooke (andrew@acooke.org) based on # a program at http://wiki.bath.ac.uk/display/~ma9mjo/iRiver+s10 # written by Martin Owen which was itself based on a program by # Laszlo Pandy (http://laszlopandy.com) which I can no longer find. # Unlike previous versions, this requires Python 3. The reason for # this is that byte / unicode handling changed and I have "fixed" the # code to handle Unicode correctly (so had to choose between Python # 2 and 3). # Another change is that the program no longer mangles file paths. # The program works as a filter - it reads a simple m3u format # playlist from stdin (ie a list of file paths) and writes a pla # format playlist to stdout (or to a file, if one is given on the # command line). from sys import argv, stdin, stdout, stderr, exit from os.path import exists from struct import pack def strTo8Bit(text): return text.encode('ascii') def strTo16Bit(text): chars = list(text.encode('utf_16')[2:]) for i in range(0, len(chars), 2): chars[i], chars[i+1] = chars[i+1], chars[i] return bytes(chars) def pad(data): return data + b'\0' * (512 - len(data)) # The three characters that must come before the file path PATH_HEADER = b'\0\x1B\0' # The header at the beginning of the file FILE_HEADER = strTo8Bit('iriver UMS PLA') \ + b'\0' * 14 + strTo8Bit('Quick List') def main(): # Check number of command line args if len(argv) > 2: print("Usage:\n ls *.mp3 | m3utopla [output-file]") exit(1) # Set output from optional command line arg if len(argv) == 2: dest = argv[1] if exists(dest): print("Output file {0} already exists".format(dest)) exit(1) out = open(dest, 'bw') else: out = stdout.buffer # Read files from stdin tracks = [] while True: track = stdin.readline() if not track: break # Change slash direction track = track.strip() tracks.append(track.replace('/', '\\')) # Write the header out.write(pad(pack('>i', len(tracks)) + FILE_HEADER)) # Write out the files for track in tracks: # print('>' + track + '<', file=stderr) offset = track.rfind('\\') + 1 out.write(pad(pack('>h', offset) + strTo16Bit(track))) out.flush() if __name__ == "__main__": main()