#!/usr/bin/python

# makes a XML playlist in the xpsf format, suitable for use with a flash music
# player such as: http://musicplayer.sourceforge.net/
# 
# For Help, type: python makeplaylist.py --help
# Known Bugs: doesn't support different images per-song
# Requires: id3reader.py, available at http://nedbatchelder.com/code/modules/id3reader.html
# 			(everything else is in your standard Python install)
# 
# Copyright (C) 2008 David Merrill
#
# 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 glob
import id3reader
from xml.dom.minidom import Document
from optparse import OptionParser

# create and configure the option parser
parser = OptionParser()
parser.add_option("-t","--title",dest="title",default=None,help="TITLE of the album. if you omit this, it will attempt to pull it from the ID3 tags of the first music file.",metavar="TITLE")
parser.add_option("-p","--pattern",dest="pattern",default="*.mp3",help="regular expression pattern to use when reading filenames, for example \"*.mp3\" (default)",metavar="PATTERN")
parser.add_option("-o","--outfile",dest="outfile",default="out.xpsf",help="OUTFILE to write the xml to. default is out.xpsf",metavar="OUTFILE")
parser.add_option("-b","--basepath",dest="basepath",default="",help="BASE PATH where the music files will actually live, for instance a URL. if your files will be served up in the same director as the flash player, you can omit this argument.",metavar="BASEPATH")
parser.add_option("-i","--image",dest="image",default="",help="IMAGE file to show on player during playback. also assumed to live at the URL referenced by BASEPATH. defaults to none",metavar="IMAGE")

# parse the args to find the title of the album
(options, args) = parser.parse_args()

# pick up the relevant files
files = glob.glob(options.pattern)

# Create the minidom document
doc = Document()	

# Create the <playlist> base element
playlist = doc.createElement("playlist")
playlist.setAttribute("version", "1")
playlist.setAttribute("xmlns", "http://xspf.org/ns/0/")
doc.appendChild(playlist)

# Create the <title> element. if not title was supplied at the command-line, 
# use the album info from the first track
if not options.title:
	id3r = id3reader.Reader(files[0])
	album_title = id3r.getValue('album')
else:
	album_title = options.title	
title = doc.createElement("title")
playlist.appendChild(title)
title.appendChild(doc.createTextNode(album_title))

# Create the trackList tag
tracklist = doc.createElement("trackList")
playlist.appendChild(tracklist)

def attach_single_text_entry(parent, name, text):
	entry = doc.createElement(name)
	entry.appendChild(doc.createTextNode(text))
	parent.appendChild(entry)
	
def make_track_XML_entry(tracklist, location, title, creator, image):
	track = doc.createElement("track")
	attach_single_text_entry(track,"location",location)
	attach_single_text_entry(track,"title",title)
	attach_single_text_entry(track,"creator",creator)
	if image:
		attach_single_text_entry(track,"image",image)
	tracklist.appendChild(track)

# handle whether they passed an image or not
if options.image:
	image = options.basepath + options.image
else:
	image = ""

# iterate across the files, and add their information to the XML doc
for file in files:	
	id3r = id3reader.Reader(file)
	make_track_XML_entry(tracklist, options.basepath + str(file), id3r.getValue('title'), id3r.getValue('performer'), image)

# write the result to a file
f = open(options.outfile, "w")
f.write(doc.toxml())
f.close()

