#!/usr/bin/python
#Audio Tools, a module and set of tools for manipulating audio data
#Copyright (C) 2007-2009 Brian Langenberger
#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 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, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import sys
import os
import audiotools
import gettext
gettext.install("audiotools",unicode=True)
if (__name__ == '__main__'):
parser = audiotools.OptionParser(
usage=_(u"%prog [options] [track #] [track #] ..."),
version="Python Audio Tools %s" % (audiotools.VERSION))
parser.add_option('-V','--verbose',
action='store',
dest='verbosity',
choices=["quiet","normal","debug"],
default="normal",
help=_(u'the verbosity level to execute at'))
parser.add_option('-c','--cdrom',action='store',
type='string',dest='cdrom',
default=audiotools.DEFAULT_CDROM)
parser.add_option('-s','--speed',action='store',
type='int',dest='speed')
conversion = audiotools.OptionGroup(parser,_(u"Conversion Options"))
conversion.add_option('-t','--type',
action='store',
dest='type',
choices=audiotools.TYPE_MAP.keys(),
default='wav',
help=_(u'the type of audio track to create'))
conversion.add_option('-q','--quality',
action='store',
type='string',
dest='quality',
help=_(u'the quality to store audio tracks at'))
conversion.add_option("-d","--dir",action='store',default='.',
dest='dir',
help=_(u"the directory to store extracted audio tracks"))
conversion.add_option('--format',
action='store',
type='string',
default=audiotools.FILENAME_FORMAT,
dest='format',
help=_(u'the format string for new filenames'))
parser.add_option_group(conversion)
metadata = audiotools.OptionGroup(parser,_(u"Metadata Options"))
metadata.add_option('-x','--xmcd',
action='store',
type='string',
dest='xmcd',
metavar='FILENAME',
help=_(u'FreeDB XMCD file or MusicBrainz XML file'))
metadata.add_option('--album-number',
dest='album_number',
action='store',
type='int',
default=0,
help=_(u'the album number of this CD, if it is one of a series of albums'))
metadata.add_option('--album-total',
dest='album_total',
action='store',
type='int',
default=0,
help=_(u'the total albums of this CD\'s set, if it is one of a series of albums'))
#if adding ReplayGain is a lossless process
#(i.e. added as tags rather than modifying track data)
#add_replay_gain should default to True
#if not, add_replay_gain should default to False
#which is which depends on the track type
metadata.add_option('--replay-gain',
action='store_true',
dest='add_replay_gain',
help=_(u'add ReplayGain metadata to newly created tracks'))
metadata.add_option('--no-replay-gain',
action='store_false',
dest='add_replay_gain',
help=_(u'do not add ReplayGain metadata in newly created tracks'))
parser.add_option_group(metadata)
(options,args) = parser.parse_args()
msg = audiotools.Messenger("cd2track",options)
#get the AudioFile class we are converted to
AudioType = audiotools.TYPE_MAP[options.type]
if (options.add_replay_gain is None):
options.add_replay_gain = AudioType.lossless_replay_gain()
#ensure the selected compression is compatible with that class
if (options.quality == 'help'):
if (len(AudioType.COMPRESSION_MODES) > 1):
msg.info(_(u"Available compression types for %s:") % \
(AudioType.NAME))
for mode in AudioType.COMPRESSION_MODES:
msg.info(mode.decode('ascii'))
else:
msg.error(_(u"Audio type %s has no compression modes") % \
(AudioType.NAME))
sys.exit(0)
elif (options.quality is None):
options.quality = AudioType.DEFAULT_COMPRESSION
elif (options.quality not in AudioType.COMPRESSION_MODES):
msg.error(_(u"\"%(quality)s\" is not a supported compression mode for type \"%(type)s\"") % \
{"quality":options.quality,
"type":AudioType.NAME})
sys.exit(1)
#if we're using an XMCD file, use that file for MetaData
if (options.xmcd is not None):
try:
xmcd = audiotools.read_metadata_file(options.xmcd)
except audiotools.MetaDataFileException,err:
msg.error(unicode(err))
sys.exit(1)
else: #if we're not using an XMCD file, no MetaData
xmcd = None
quality = options.quality
base_directory = options.dir
try:
cdda = audiotools.CDDA(options.cdrom,options.speed)
except IOError, err:
msg.error(unicode(err) + _(u". Is that an audio cd ?"))
sys.exit(-1)
if (len(cdda) == 0):
msg.error(_(u"No CD in drive"))
sys.exit(1)
encoded = []
if (len(args) == 0):
to_rip = [track for track in cdda]
else:
to_rip = []
for arg in args:
try:
to_rip.append(cdda[int(arg)])
except IndexError:
continue
except ValueError:
continue
to_rip.sort(lambda x,y: cmp(x.track_number,y.track_number))
for cd_track in to_rip:
try:
if (xmcd is not None): #we have metadata
try:
metadata = xmcd[cd_track.track_number]
if (options.album_number != 0):
metadata.album_number = options.album_number
if (options.album_total != 0):
metadata.album_total = options.album_total
except KeyError:
metadata = None
filename = os.path.join(
base_directory,
AudioType.track_name(cd_track.track_number,
track_metadata=metadata,
album_number=options.album_number,
format=options.format))
audiotools.make_dirs(filename)
track = AudioType.from_pcm(
filename,
cd_track,
quality)
track.set_metadata(metadata)
encoded.append(track)
else: #no metadata
filename = os.path.join(
base_directory,
AudioType.track_name(cd_track.track_number,
track_metadata=None,
album_number=options.album_number,
format=options.format))
audiotools.make_dirs(filename)
track = AudioType.from_pcm(
filename,
cd_track,
quality)
#even if no MetaData is given,
#set track number and album number if possible
track.set_metadata(audiotools.MetaData(
track_number=cd_track.track_number,
track_total=len(cdda),
album_number=options.album_number,
album_total=options.album_total))
encoded.append(track)
msg.info(_(u"track %(track_number)2.2d: %(log)s") % \
{"track_number":cd_track.track_number,
"log":str(cd_track.rip_log)})
msg.info(_(u"track %(track_number)2.2d -> %(filename)s") % \
{"track_number":cd_track.track_number,
"filename":msg.filename(track.filename)})
except audiotools.UnsupportedTracknameField,err:
err.error_msg(msg)
sys.exit(1)
except KeyError:
continue
except audiotools.InvalidFormat,err:
msg.error(unicode(err))
sys.exit(1)
except audiotools.EncodingError,err:
msg.error(_(u"Unable to write \"%s\"") % (msg.filename(filename)))
sys.exit(1)
cdda.close()
if (options.add_replay_gain and AudioType.can_add_replay_gain()):
if (AudioType.lossless_replay_gain()):
msg.info(_(u"Adding ReplayGain metadata. This may take some time."))
else:
msg.info(_(u"Applying ReplayGain. This may take some time."))
AudioType.add_replay_gain([track.filename for track in encoded])