#!/usr/bin/python
# BPM-Tag
# Copyright (c) 2006 Erich Schubert erich@debian.org

#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:

#The above copyright notice and this permission notice shall be included in
#all copies or substantial portions of the Software.

#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#SOFTWARE.

##################

# Version history:
# Version 0.1:
#   * handle mp3 and ogg vorbis, tag BPM and frequency overview
# Version 0.2:
#   * better handling of broken files, and files with no ID3 tag yet.
#
# Let me emphasize: you need gjay from CVS, for --analyze-standalone
#

import os, sys
from subprocess import Popen, PIPE
from elementtree import ElementTree
from mutagen import id3, oggvorbis
from xml.parsers.expat import ExpatError

extensions = [ ".mp3", ".ogg" ]

def process_dir(dir):
	"""
	Process a single directory tree
	"""
	if not os.access(dir, os.F_OK):
		sys.stderr.write("Could not access directory %s\n" % dir)
		return
	for p, dirs, files in os.walk(dir):
		for f in files:
			fullname = os.path.join(p, f)
			(path, ext) = os.path.splitext(fullname)
			if ext in extensions:
				process_file(fullname)

def process_file(file):
	(path, ext) = os.path.splitext(file)
	f = None
	if ext == ".mp3":
		try:
			f = id3.ID3(file)
			if not f:
				sys.stderr.write("File %s not recognized by mutagen.\n" % file)
				return
		except id3.ID3NoHeaderError:
			f = id3.ID3()
		if f.has_key("TBPM") and f["TBPM"] == "undef":
			sys.stderr.write("Removing 'undef' BPM value from file %s.\n" % file)
			del f["TBPM"]
		if f.has_key("TBPM"):
			#sys.stdout.write("File %s already has BPM information.\n" % file)
			return
	elif ext == ".ogg":
		f = oggvorbis.OggVorbis(file)
		if f.has_key("BPM"):
			#sys.stdout.write("File %s already has BPM information.\n" % file)
			return
	else:
		sys.stderr.write("File %s not supported.\n" % file)
		return

	p = Popen(["gjay", "--analyze-standalone", file],
		stdin=PIPE, stdout=PIPE, close_fds=True)
	p.stdin.close()
	lines = "".join(p.stdout.readlines())
	try:
		tree = ElementTree.XML(lines)
	except ExpatError:
		sys.stderr.write("File %s caused invalid XML markup by gjay!\n" % file)
		return
	bpm = tree.findtext("bpm")
	if bpm == "undef":
		sys.stderr.write("BPM calculation failed for %s\n" % file)
	freq = tree.findtext("freq")

	if ext == ".mp3":
		if bpm != "undef":
			f.add(id3.Frames['TBPM'](encoding=3, text=bpm))
		f.add(id3.Frames['TXXX'](encoding=3, desc=u"Gjay Freq", text=freq))
		f.save(file)
	elif ext == ".ogg":
		if bpm != "undef":
			f["BPM"] = bpm
		f["GjayFreq"] = freq
		f.save(file)

for dir in sys.argv[1:]:
	process_dir(dir)
