Add --no-hash option to mkogg.py.
authorW. Trevor King <wking@drexel.edu>
Thu, 15 Dec 2011 18:52:01 +0000 (13:52 -0500)
committerW. Trevor King <wking@drexel.edu>
Thu, 15 Dec 2011 18:52:01 +0000 (13:52 -0500)
Hashing is slow, so now you can avoid computing hashes to determine if
the target file has changed.  You can miss small changes this way
(e.g. tag changes in the source, or changed tag handling in mkogg.py
itself), but sometimes I don't care about that enough to want to hash
my whole music collection ;).

I've also added a few more ignored and translated ID3v2 keys.

posts/mkogg/mkogg.py

index f5a10b03ef3988df828288be3e34fe57a0886c68..3ac562103e64e8d9bf17875f614e7eff3c19ca95 100755 (executable)
@@ -79,13 +79,14 @@ class Converter (object):
     .. _suggestions: http://www.xiph.org/vorbis/doc/v-comment.html
     """
     def __init__(self, source_dir, target_dir, target_extension='ogg',
-                 cache_file=None, ignore_function=None):
+                 cache_file=None, hash=True, ignore_function=None):
         self.source_dir = source_dir
         self.target_dir = target_dir
         self._source_extensions = ['flac', 'mp3', 'ogg', 'wav']
         self._target_extension = target_extension
         self._cache_file = cache_file
         self._cache = self._read_cache()
+        self._hash = hash
         self._ignore_function = ignore_function
         f,self._tempfile = mkstemp(prefix='mkogg-')
 
@@ -152,11 +153,15 @@ class Converter (object):
             os.makedirs(target_dir)
 
     def _convert(self, source, target, ext):
-        cache_key = self._cache_key(source)
-        old_cache_value = self._cache.get(cache_key, None)
-        if (old_cache_value != None and
-            old_cache_value == self._cache_value(target)):
-            print 'cached %s to %s' % (source, target)
+        if self._hash:
+            cache_key = self._cache_key(source)
+            old_cache_value = self._cache.get(cache_key, None)
+            if (old_cache_value != None and
+                old_cache_value == self._cache_value(target)):
+                print 'already cached %s to %s' % (source, target)
+                return
+        elif os.path.exists(target):
+            print 'target %s already exists' % (target)
             return
         print 'convert %s to %s' % (source, target)
         if ext == self._target_extension:
@@ -171,6 +176,8 @@ class Converter (object):
             set_metadata = getattr(self, 'set_%s_metadata'
                                    % self._target_extension)
             set_metadata(target, metadata)
+        if not self._hash:
+            cache_key = self._cache_key(source)
         self._cache[cache_key] = self._cache_value(target)
 
     def _cache_key(self, source):
@@ -237,7 +244,7 @@ class Converter (object):
         ...     'id3v2 tag info for src/03-Drive_My_Car.mp3:',
         ...     'TALB (Album/Movie/Show title): The Famous Album',
         ...     'TPE1 (Lead performer(s)/Soloist(s)): No One You Know',
-        ...     'TIT2 (Title/songname/content description): The Famous Song',
+        ...     'TT2 (Title/songname/content description): The Famous Song',
         ...     'TYER (Year): 1965',
         ...     'TCON (Content type): Rock (17)',
         ...     'TRCK (Track number/Position in set): 07/14']))
@@ -263,7 +270,7 @@ class Converter (object):
             'tpe2': 'accompaniment',
             'tpe3': 'conductor',
             'tpos': 'part of set',
-            'tpub': 'organization',
+            'tpub': 'organization',  # publisher
             'trck': 'tracknumber',
             'tyer': 'date',
             }
@@ -272,7 +279,9 @@ class Converter (object):
             'geob',  # general encapsulated object
             'ncon',  # ?
             'pcnt',  # play counter (incremented with each play)
+            'pic',   # attached picture
             'priv',  # private
+            'tbp',   # beats per minute
             'tco',   # content type
             'tcp',   # frame?
             'tenc',  # encoded by
@@ -280,6 +289,11 @@ class Converter (object):
             'tope',  # original artist (e.g. for a cover)
             'tlen',  # length (in milliseconds)
             'tmed',  # media type
+            'txxx',  # user defined text information
+            'ufi',   # unique file identifier
+            'uslt',  # unsynchronized lyric/text transcription
+            'wcom',  # commercial information
+            'woar',  # official artist/performer webpage
             'wxxx',  # user defined URL
             ]
         key_translations = {
@@ -289,6 +303,7 @@ class Converter (object):
             'tcm': 'tcom',
             'tt2': 'tit2',
             'tp1': 'tpe1',
+            'tpa': 'tpos',
             'trk': 'trck',
             'tye': 'tyer',
             }
@@ -474,6 +489,10 @@ if __name__ == '__main__':
     p.add_option('-c', '--cache', dest='cache', metavar='PATH',
                  help=('Save conversion hashes in a cache file to avoid '
                        'repeated previous conversions.'))
+    p.add_option('-n', '--no-hash', dest='hash', action='store_false',
+                 default=True,
+                 help=("Don't hash files.  Just assume matching names would "
+                       'have matching hashes.'))
     p.add_option('-i', '--ignore', dest='ignore', metavar='REGEXP',
                  help=('Ignore source paths matching REGEXP.'))
     p.add_option('--test', dest='test', action='store_true', default=False,
@@ -492,7 +511,8 @@ if __name__ == '__main__':
 
     source_dir,target_dir = args
     c = Converter(source_dir, target_dir, target_extension=options.ext,
-                  cache_file=options.cache, ignore_function=ignore_function)
+                  cache_file=options.cache, hash=options.hash,
+                  ignore_function=ignore_function)
     try:
         c.run()
     finally: