From: Simeon Veldstra Date: Sun, 10 Jun 2007 04:23:45 +0000 (-0700) Subject: Merge with bugfix-0.5 X-Git-Tag: v0.5.12 X-Git-Url: http://puddle.ca/cgi-bin/gitweb.cgi?p=mp3togo;a=commitdiff;h=545d8d053ed03212f1d04dff14a202c109580ecd Merge with bugfix-0.5 --- --- a/README +++ b/README @@ -1,7 +1,7 @@ mp3togo -(C) 2004 - 2006 Simeon Veldstra +(C) 2004 - 2007 Simeon Veldstra INSTALLING --- a/copyright +++ b/copyright @@ -2,7 +2,7 @@ mp3togo Software to manage playlists for mp3 players. -(C) Copyright 2004-2006 Simeon Veldstra +(C) Copyright 2004-2007 Simeon Veldstra Some rights reserved. This software is free and may be redistributed under the --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,16 @@ +mp3togo (0.5.11) unstable; urgency=low + + * Fixed ommited year and tracknumber tags on mp3 conversions using eyeD3. + Reported by Konstantin Pastbin. + + -- Simeon Veldstra Sat, 09 Jun 2007 20:31:05 -0700 + +mp3togo (0.5.10) unstable; urgency=low + + * Made quiet mode really quiet. Fixed -m option. + + -- Simeon Veldstra Mon, 12 Feb 2007 19:25:48 -0800 + mp3togo (0.5.9) unstable; urgency=low * Added -u update switch for conditional --force. Thanks Mark J. Hewitt. --- a/debian/mp3togo.1 +++ b/debian/mp3togo.1 @@ -134,4 +134,4 @@ License can be found in /usr/share/commo .PP mp3togo can be found online at http://puddle.ca/mp3togo -.\" created by instant / docbook-to-man, Sun 04 Feb 2007, 16:42 +.\" created by instant / docbook-to-man, Sat 09 Jun 2007, 20:36 --- a/mp3togo/conf.py +++ b/mp3togo/conf.py @@ -107,7 +107,7 @@ class Options(options.Options): '''The encoder to use to create the output files. Options are wav, lame or oggenc.'''), ('encopts', 'E', 'encoder-options', '', None, '''Compression options for the encoder.'''), - ('compfactor', 'z', 'compression-factor', 16.0, None, + ('compfactor', 'z', 'compression-factor', 18.0, None, '''If you change the lame options, you must change this factor to match the compression rate of the new options. This is used to estimate completed file size.'''), ('makecache', '', 'make-cache', '', self._absfile, '''Make an output file cache at the given path.'''), ('cachesize', '', '', 0L, None, ''), @@ -207,6 +207,8 @@ Description: def _units(self, name, value): #Calculate raw bytes and set [max|temp|cache]size try: + if value[-1] in ('b', 'B'): + value = value[:-1] if value[-1] in ('m', 'M'): max = long(value[:-1]) * 1048576L elif value[-1] in ('g', 'G'): --- a/mp3togo/main.py +++ b/mp3togo/main.py @@ -148,8 +148,14 @@ def main(argv): def execute_sequential(playlist, opts, cooked=None): """Run the conversions one at a time""" - print "mp3togo %s\n" % mp3togo.version - print " or 'p' to pause, or 'q' to quit\n" + # shouldn't print if verbose is 0: + if opts['verbosity']: + tryp = conf.try_print + else: + tryp = lambda x: None + + tryp("mp3togo %s\n\n" % mp3togo.version) + tryp(" or 'p' to pause, or 'q' to quit\n\n") c = '' start_time = time.time() good_ones = 0 @@ -158,25 +164,27 @@ def execute_sequential(playlist, opts, c try: # Terminal sushi - fd = sys.stdin.fileno() - oldterm = termios.tcgetattr(fd) - newattr = termios.tcgetattr(fd) - newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO - termios.tcsetattr(fd, termios.TCSANOW, newattr) - - oldflags = fcntl.fcntl(fd, fcntl.F_GETFL) - fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK) - + raw = False if opts['verbosity']: - tryp = conf.try_print - else: - tryp = lambda x: None + try: + fd = sys.stdin.fileno() + oldterm = termios.tcgetattr(fd) + newattr = termios.tcgetattr(fd) + newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO + termios.tcsetattr(fd, termios.TCSANOW, newattr) + oldflags = fcntl.fcntl(fd, fcntl.F_GETFL) + fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK) + raw = True + except: + fail('Error setting the terminal to raw mode.\nIs this a tty?') + + pl = pool.Pool(opts) # make a new one for every track? Huh? for name in playlist: track_start = time.time() tryp("(%d/%d) %s: \n" % (playlist.cur_file() + 1, len(playlist), name)) trk = track.Track(name, opts, cooked) - pl = pool.Pool(opts) # make a new one for every track? Huh? + #pl = pool.Pool(opts) # make a new one for every track? Huh? if pl.add_track(trk): tsk = trk.getfirst() try: @@ -237,8 +245,7 @@ def execute_sequential(playlist, opts, c tryp("Undo: %s\n" % tsk.name) tsk.undo() tsk = tsk.prev() - sys.exit(1) - pass + break else: opts.log(1, "Out of space. Exiting.") break @@ -267,14 +274,40 @@ def execute_sequential(playlist, opts, c bad_str = ", %d tracks failed." % bad_ones else: bad_str = "." - #bytes = format_bytes(pl.produced_bytes) # you are using a new pool each time! - tryp("\n%d tracks done%s %s total time elapsed.\n" % - (good_ones, bad_str, ts)) + bytes = format_bytes(pl.produced_bytes) + tryp("\n%s written for %d tracks%s %s total time elapsed.\n" % + (bytes, good_ones, bad_str, ts)) finally: # Fry some fish: - termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm) - fcntl.fcntl(fd, fcntl.F_SETFL, oldflags) + if raw: + termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm) + fcntl.fcntl(fd, fcntl.F_SETFL, oldflags) + + +def format_time(tm): + tm = int(tm) + if tm: + hr, min, sec = (tm/3600, (tm%3600)/60, (tm%3600)%60) + ts = "%ds " % sec + if min > 0: + ts = ("%dm " % min) + ts + if hr > 0: + ts = ("%dh " % hr) + ts + return ts[:-1] + else: + return '' + +def format_bytes(bytes): + k = 1024.0 + m = 1024 * k + g = 1024 * m + if k <= bytes < m: + return "%.2f KB" % (bytes/k) + elif m <= bytes: # < g: + return "%.2f MB" % (bytes/m) + else: + return str(bytes) + " Bytes" if __name__ == "__main__": main(sys.argv) --- a/mp3togo/tags.py +++ b/mp3togo/tags.py @@ -95,18 +95,27 @@ class Tags(UserDict.DictMixin): return o if self._type == 'mp3' and HAVE_ID3: + rok = False if HAVE_eyeD3: eye = eyeD3.Tag() - eye.link(self._file) - self._tags['ARTIST'] = [eye.getArtist() or ''] - self._tags['ALBUM'] = [eye.getAlbum() or ''] - self._tags['TITLE'] = [eye.getTitle() or ''] try: - self._tags['GENRE'] = [getattr(eye.getGenre(), 'name', 'Other')] - except eyeD3.tag.GenreException: - self._tags['GENRE'] = 'Other' - del eye - elif HAVE_ID3: + eye.link(self._file) + self._tags['ARTIST'] = [eye.getArtist() or ''] + self._tags['ALBUM'] = [eye.getAlbum() or ''] + self._tags['TITLE'] = [eye.getTitle() or ''] + if eye.getYear() and eye.getYear() > 1600 and eye.getYear() < 3000: + self._tags['DATE'] = [eye.getYear()] + if eye.getTrackNum(): + self._tags['TRACKNUMBER'] = [str(eye.getTrackNum()[0])] + try: + self._tags['GENRE'] = [getattr(eye.getGenre(), 'name', 'Other')] + except eyeD3.tag.GenreException: + self._tags['GENRE'] = 'Other' + del eye + rok = True + except eyeD3.tag.TagException: + pass + if HAVE_ID3 and not rok: info = ID3.ID3(self._file, as_tuple=1).as_dict() self._tags = copytags(info) del info @@ -158,7 +167,10 @@ class Tags(UserDict.DictMixin): elif self._tags[key][0] in map(str, range(256)): d[key] = int(self._tags[key][0]) else: - d[key] = int(genres.get(self._tags[key][0], '255')) + try: + d[key] = int(genres.get(self._tags[key][0], '255')) + except: + d[key] = 12 else: d[key] = self._tags[key][0] # No! don't unlock here dumbass! return from puttags @@ -192,6 +204,16 @@ class Tags(UserDict.DictMixin): out.setTitle(d['TITLE']) g = eyeD3.Genre() g.setId(d.get('GENRE', 12)) + try: + if d.has_key('DATE') and int(d['DATE']) > 1600 and int(d['DATE']) < 3000: + out.setDate(d['DATE']) + except: + pass + if d.has_key('TRACKNUMBER') and d['TRACKNUMBER']: + try: + out.setTrackNum((int(d['TRACKNUMBER']), None)) + except: + pass out.setGenre(g) if d.has_key('COMMENT'): out.addComment(d['COMMENT']) --- a/mp3togo/track.py +++ b/mp3togo/track.py @@ -28,18 +28,11 @@ import mp3togo.task as task import mp3togo.cache as cache from mp3togo.helpers import helpers -#helpers = mp3togo.helpers.helpers - - READY = "ready" RUNNING = "running" DONE = 0 FAILED = None -DOGGFACTOR = 10 -DMP3FACTOR = 10 -DFLACFACTOR = 3 - class Track: """Encapsulate the transformation of a file.""" @@ -233,7 +226,13 @@ class Track: # tag files from the cache as well, brwarning may have changed if not opts['notags']: def tag_output(): - self.tags.write(self._outname) + try: + self.tags.write(self._outname) + except: + if opts['verbosity'] > 3: + import sys, traceback + traceback.print_exc(file=sys.stdout) + raise return True job = task.SimpleTask(self, tag_output, None, lambda: True, name="Tagging") @@ -255,16 +254,6 @@ class Track: tasks.append(job) del job - ## Consider the track done if the output file exists: - #if os.path.exists(self._outname) and not opts['force']: - # opts.log(1, "Skipping existing file: %s\n" % self._outname) - # self._queue = tuple(tasks) - # if self._hash and self._cache: - # self._cache.release(self._hash) - # for tsk in self._queue: - # tsk._status = task.DONE - # self._state = DONE - # return if not opts['force']: if os.path.exists(self._outname): # In update mode, consider the track done if an existing file is older than the source @@ -278,6 +267,7 @@ class Track: self._cache.release(self._hash) for tsk in self._queue: tsk._status = task.DONE + self.bytes = os.stat(self._outname).st_size self._state = DONE return else: @@ -289,6 +279,7 @@ class Track: self._cache.release(self._hash) for tsk in self._queue: tsk._status = task.DONE + self.bytes = os.stat(self._outname).st_size self._state = DONE return