Advertisement
Guest User

goobsoft

a guest
Nov 21st, 2008
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.75 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. import sys
  4. from optparse import OptionParser
  5.  
  6. import mutagen
  7. from mutagen.apev2 import APEv2
  8. from mutagen.id3 import ID3, TXXX
  9.  
  10.  
  11. def convert_gain(gain):
  12.    if gain[-3:] == " dB":
  13.        gain = gain[:-3]
  14.    try:
  15.        gain = float(gain)
  16.    except ValueError:
  17.        raise ValueError, "invalid gain value"
  18.    return "%.2f dB" % gain
  19.  
  20. def convert_peak(peak):
  21.    try:
  22.        peak = float(peak)
  23.    except ValueError:
  24.        raise ValueError, "invalid peak value"
  25.    return "%.6f" % peak
  26.  
  27.  
  28. REPLAYGAIN_TAGS = (
  29.    ("replaygain_album_gain", convert_gain),
  30.    ("replaygain_album_peak", convert_peak),
  31.    ("replaygain_track_gain", convert_gain),
  32.    ("replaygain_track_peak", convert_peak),
  33. )
  34.  
  35.  
  36. class Logger(object):
  37.    def __init__(self, log_level, prog_name):
  38.        self.log_level = log_level
  39.        self.prog_name = prog_name
  40.        self.filename = None
  41.  
  42.    def prefix(self, msg):
  43.        if self.filename is None:
  44.            return msg
  45.        return "%s: %s" % (self.filename, msg)
  46.  
  47.    def debug(self, msg):
  48.        if self.log_level >= 4:
  49.            print self.prefix(msg)
  50.  
  51.    def info(self, msg):
  52.        if self.log_level >= 3:
  53.            print self.prefix(msg)
  54.  
  55.    def warning(self, msg):
  56.        if self.log_level >= 2:
  57.            print self.prefix("WARNING: %s" % msg)
  58.  
  59.    def error(self, msg):
  60.        if self.log_level >= 1:
  61.            sys.stderr.write("%s: %s\n" % (self.prog_name, msg))
  62.  
  63.    def critical(self, msg, retval=1):
  64.        self.error(msg)
  65.        sys.exit(retval)
  66.  
  67.  
  68. class Ape2Id3(object):
  69.    def __init__(self, logger, force=False):
  70.        self.log = logger
  71.        self.force = force
  72.  
  73.    def convert_tag(self, name, value):
  74.        pass
  75.  
  76.    def get_value(self, apev2, name):
  77.        if apev2.has_key(name):
  78.            return str(apev2[name])
  79.  
  80.        if apev2.has_key(name.upper()):
  81.            return str(apev2[name.upper()])
  82.  
  83.        return None
  84.  
  85.    def copy_replaygain_tag(self, apev2, id3, name, converter=None):
  86.        self.log.debug("processing '%s' tag" % name)
  87.  
  88.        if not self.force and id3.has_key("TXXX:%s" % name):
  89.            self.log.info("ID3 '%s' tag already exists, skpping tag" % name)
  90.            return False
  91.  
  92.        value = self.get_value(apev2, name)
  93.        if value == None:
  94.            self.log.warning("no APEv2 '%s' tag found, skipping tag" % name)
  95.            return False
  96.  
  97.        if callable(converter):
  98.            self.log.debug("converting APEv2 '%s' tag from '%s'" %
  99.                           (name, value))
  100.            try:
  101.                value = converter(value)
  102.            except ValueError:
  103.                self.log.warning("invalid value for APEv2 '%s' tag" % name)
  104.                return False
  105.            self.log.debug("converted APEv2 '%s' tag to '%s'" % (name, value))
  106.  
  107.        id3.add(TXXX(encoding=1, desc=name, text=value))
  108.        self.log.info("added ID3 '%s' tag with value '%s'" % (name, value))
  109.        return True
  110.  
  111.    def copy_replaygain_tags(self, filename):
  112.        self.log.filename = filename
  113.        self.log.debug("begin processing file")
  114.  
  115.        try:
  116.            apev2 = APEv2(filename)
  117.        except mutagen.apev2.error:
  118.            self.log.info("no APEv2 tag found, skipping file")
  119.            return
  120.        except IOError:
  121.            print "ioerror"
  122.            e = sys.exc_info()
  123.            self.log.error("%s" % e[1])
  124.            return
  125.  
  126.        try:
  127.            id3 = ID3(filename)
  128.        except mutagen.id3.error:
  129.            self.log.info("no ID3 tag found, creating one")
  130.            id3 = ID3()
  131.  
  132.        modified = False
  133.        for name, converter in REPLAYGAIN_TAGS:
  134.            copied = self.copy_replaygain_tag(apev2, id3, name, converter)
  135.            if copied:
  136.                modified = True
  137.        if modified:
  138.            self.log.debug("saving modified ID3 tag")
  139.            id3.save(filename)
  140.  
  141.        self.log.debug("done processing file")
  142.        self.log.filename = None
  143.  
  144.  
  145. def main(prog_name, options, args):
  146.    logger = Logger(options.log_level, prog_name)
  147.    ape2id3 = Ape2Id3(logger, force=options.force)
  148.    for filename in args:
  149.        try:
  150.            apev2 = APEv2(filename)
  151.            for key in apev2.keys():
  152.                print key, apev2[key]
  153.        except mutagen.apev2.error:
  154.            self.log.info("no APEv2 tag found, skipping file")
  155.            return
  156.        except IOError:
  157.            print "ioerror"
  158.            e = sys.exc_info()
  159.            self.log.error("%s" % e[1])
  160.            return
  161.  
  162.        ape2id3.copy_replaygain_tags(filename)
  163.  
  164.  
  165. if __name__ == "__main__":
  166.    parser = OptionParser(version="0.1", usage="%prog [OPTION]... FILE...",
  167.                          description="Copy APEv2 ReplayGain tags on "
  168.                                      "FILE(s) to ID3v2.")
  169.    parser.add_option("-q", "--quiet", dest="log_level",
  170.                      action="store_const", const=0, default=1,
  171.                      help="do not output error messages")
  172.    parser.add_option("-v", "--verbose", dest="log_level",
  173.                      action="store_const", const=3,
  174.                      help="output warnings and informational messages")
  175.    parser.add_option("-d", "--debug", dest="log_level",
  176.                      action="store_const", const=4,
  177.                      help="output debug messages")
  178.    parser.add_option("-f", "--force", dest="force",
  179.                      action="store_true", default=False,
  180.                      help="force overwriting of existing ID3v2 "
  181.                           "ReplayGain tags")
  182.    prog_name = parser.get_prog_name()
  183.    options, args = parser.parse_args()
  184.  
  185.    if len(args) < 1:
  186.        parser.error("no files specified")
  187.  
  188.    try:
  189.        main(prog_name, options, args)
  190.    except KeyboardInterrupt:
  191.        pass
  192.  
  193.  
  194. # vim: set expandtab shiftwidth=4 softtabstop=4 textwidth=79:
  195.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement