#! /usr/bin/env python
#
# Transcode audio files to Ogg Vorbis, preserving tags if there are any.
#
# Copyright (c) 2008, Matthias Friedrich <matt@mafr.de>
#
# 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 2, 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.
#
import sys
import os.path
import optparse
import gobject
import gst


gobject.threads_init()
mainloop = gobject.MainLoop()

op = optparse.OptionParser("usage: %prog [options] filenames...")
op.add_option('-d', '--dest-dir', dest='destinationDir',
	help='Create files in directory DIR', metavar='DIR')

(options, args) = op.parse_args()



def err_quit(msg):
	print >>sys.stderr, '%s: %s' % (op.get_prog_name(), msg)
	sys.exit(1)

def on_eos(bus, msg):
	mainloop.quit()

def on_error(bus, msg):
	error = msg.parse_error()
	mainloop.quit()
	pipeline.set_state(gst.STATE_NULL)
	err_quit(error[1])


def create_pipeline(inputfile, outputfile):
	"""Create a gstreamer transcoding pipeline."""

	pipeline = gst.parse_launch("""
		filesrc name=in
		! decodebin ! audioconvert ! vorbisenc ! oggmux
		! filesink name=out
	"""); 

	src = pipeline.get_by_name('in')
	src.set_property('location', inputfile)

	sink = pipeline.get_by_name('out')
	sink.set_property('location', outputfile)

	bus = pipeline.get_bus()
	bus.add_signal_watch()
	bus.connect('message::eos', on_eos)
	bus.connect('message::error', on_error)

	return pipeline


def mkdir(dirname):
	"""Create the directory if it doesn't exist."""
	if not os.path.exists(dirname):
		os.makedirs(dirname)
	elif os.path.exists(dirname) and not os.path.isdir(dirname):
		err_quit('%s exists and is no directory' % (dirname, ))


# Transcode all files passed via the command line.
#
for inputFileName in args:
	inputDir, inputBaseName = os.path.split(inputFileName)

	# We drop files next to the source file unless the user requested
	# a different output directory.
	#
	destDir = options.destinationDir or inputDir or '.'
	mkdir(destDir)

	oggFileName = os.path.join(
		destDir, os.path.splitext(inputBaseName)[0] + '.ogg')

	print "from %s to %s" % (inputFileName, oggFileName)

	try:
		pipeline = create_pipeline(inputFileName, oggFileName)
		pipeline.set_state(gst.STATE_PLAYING)

		mainloop.run()

	except KeyboardInterrupt:
		err_quit('Interrupted on user request.')
	finally:
		pipeline.set_state(gst.STATE_NULL)

# EOF
