[mp3togo] audiotags diff

Justus Pendleton justus at ryoohki.net
Sun May 28 21:42:57 PDT 2006


Here is a patch to change mp3togo over to using the audiotags library I 
posted earlier. It is actually pretty small. Most of tags.py goes away 
with this change. A few functions got changed from methods to regular 
functions. I've only tested it on a few mp3s this evening but it seems 
to be working as expected.
-------------- next part --------------
=== modified file 'mp3togo/main.py'
--- mp3togo/main.py	
+++ mp3togo/main.py	
@@ -48,7 +48,6 @@
 	sys.exit(code)
 
 def main(argv):
-
 	# Read in configuration
 	try:
 		opts = conf.Options(argv)

=== modified file 'mp3togo/tags.py'
--- mp3togo/tags.py	
+++ mp3togo/tags.py	
@@ -19,298 +19,66 @@
 
 
 import os, sys
-import UserDict
-import threading
 
 import mp3togo.conf as setup
 
 # This mess needs to be fixed,
 # Tags() is just going to have to
 # take an Options() instance.
-try:
-	import ogg.vorbis
-except ImportError:
-	HAVE_VORBIS = False
-else:
-	HAVE_VORBIS = True
-
-try:
-	import ID3
-except ImportError:
-	HAVE_ID3 = False
-else:
-	HAVE_ID3 = True
-
-HAVE_METAFLAC=False
-for path in os.environ['PATH'].split(':'):
-	if os.path.exists(os.path.join(path, 'metaflac')):
-		HAVE_METAFLAC=True
-		break
-
-
-class Tags(UserDict.DictMixin):
-	"""Manage per track metadata.
-
-	Provide a filename in the constructor
-	Call read() to read in the tags
-	modify tags if necessary
-	Call write(name) with the output file the tags
-	are to be written to
-	Tags are available through a dictionary interface
-	format(fmt) returns a formatted string of metadata
-	"""
-
-	def __init__(self, filename):
-		if not os.path.exists(filename):
-			raise setup.ErrorNoFile
-		self._file = filename
-		self._type = setup.getfiletype(filename)
-		self._tags = {}
-		self._readok = threading.Event()
-		self._readok.clear()
-		self._lock = threading.Lock()
-
-
-	def read(self, block=True):
-		if not self._lock.acquire(block) and not block:
-			return False
-		self._readok.clear()
-
-		def copytags(d):
-			o = {}
-			for k in d.keys():
-				o[k] = list(d[k])
-			return o
-
-		if self._type == 'mp3' and HAVE_ID3:
-			info = ID3.ID3(self._file, as_tuple=1).as_dict()
-			self._tags = copytags(info) 
-			del info
-		elif self._type == 'ogg' and HAVE_VORBIS:
-			info = ogg.vorbis.VorbisFile(self._file).comment().as_dict()
-			self._tags = copytags(info) 
-			del info
-		elif self._type == 'flac' and HAVE_METAFLAC:
-			cmd = '%s --export-tags-to=- "%s" ' % ('metaflac', self._file)
-			fd = os.popen(cmd)
-			info = fd.read()
-			fd.close()
-			info = map(lambda  x: x.split('=', 1), info.split('\n'))
-			info = filter(lambda x: len(x) == 2, info)
-			info = map(lambda x: [x[0].upper(), x[1:]], info)
-			self._tags = dict(info)
-		elif self._type == 'wav':
-			pass
-			
-
-		# Try to guess from the file's path - better than nothing
-		path = os.path.splitext(self._file)[0]
-		path = path.replace('_', ' ')
-		for id, depth in [('ARTIST', -3), ('ALBUM', -2), ('TITLE', -1)]:
-			if not id in self._tags or self._tags[id][0] == '':
-				try:
-					self._tags[id] = [path.split(os.sep)[depth]]
-				except IndexError:
-					self._tags[id] = "%s unknown" % id.lower()
-
-		self._readok.set()
-		self._lock.release()
-		return True
-
-
-	def write(self, filename, block=True):
-		if not self._lock.acquire(block) and not block:
-			return False
-
-		if not os.path.exists(filename):
-			self._lock.release()
-			raise setup.ErrorNoFile
-
-		def puttags(d):
-			for key in self._tags.keys():  # Not self.keys()
-				if key == 'GENRE' and fmt == 'mp3':
-					if type(self._tags[key][0]) is type(1) and 0 <= self._tags[key][0] < 256:
-						d[key] = self._tags[key][0]
-					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'))
-				else:	
-					d[key] = self._tags[key][0]
-			# No! don't unlock here dumbass! return from puttags
-			return d
-
-		try:
-			fmt = setup.getfiletype(filename)
-		except setup.ErrorUnknownFileType:
-			self._lock.release()
-			raise
-
-		if fmt == 'ogg':
-			vf = ogg.vorbis.VorbisFile(filename)
-			out = vf.comment()
-			puttags(out)
-			try:
-				out.write_to(filename)
-			except:
-				pass
-			del out
-			del vf
-		elif fmt == 'mp3':
-			out = ID3.ID3(filename, as_tuple=1)
-			puttags(out)
-			try:
-				out.write()
-			except:
-				# Tagging failed, but the file should be okay.
-				pass
-			del out
+
+def writeindex(tags, filename, indexname):
+	try:
+		ifile = file(indexname, 'a')
+		ifile.write(filename + "\n")
+		keys = tags.keys()
+		keys.sort()
+		for k in keys:
+			for q in tags[k]:
+				ifile.write("%s: %s\n" % (k, q))
+		ifile.write("\n")
+		ifile.close()
+	except:
+		raise
+
+	return True
+
+def format(tags, fmt):
+	"""Pretty print the tag information
+
+	The following format strings apply:
+	%%     Literal %
+	%n     Track number
+	%a     Artist
+	%t     Track title
+	%l     Album title
+	%y     Album release year
+	%g     Album genre"""
+
+	esc = {'n': 'tracknumber',
+	       'a': 'artist',
+		   't': 'title',
+		   'l': 'album',
+		   'y': 'year',
+		   'g': 'genre'}
+		  #'z': Used for literal '%'
+
+	out = ""
+	fmt = fmt.replace('%%', '%z')
+	fmt = fmt.split('%')
+	while fmt:
+		out += fmt[0] 
+		if len(fmt) <= 1: 
+			break
+		fmt = fmt[1:]
+		code = fmt[0] and fmt[0][0]
+		if code == 'z':
+			fmt[0] = '%' + fmt[0][1:]
+		elif code in esc.keys():
+			fmt[0] = tags[esc[code]] + fmt[0][1:]
 		else:
-			self._lock.release()
-			raise setup.ErrorUnknownFileType
-
-		self._lock.release()
-		return True
-
-
-	def writeindex(self, filename, indexname, block=True):
-		if not self._lock.acquire(block) and not block:
-			return False
-
-		try:
-			ifile = file(indexname, 'a')
-			ifile.write(filename + "\n")
-			keys = self._tags.keys()
-			keys.sort()
-			for k in keys:
-				for q in self._tags[k]:
-					ifile.write("%s: %s\n" % (k, q))
-			ifile.write("\n")
-			ifile.close()
-		except:
-			self._lock.release()
-			raise
-
-		self._lock.release()
-		return True
-
-	def format(self, fmt, block=True):
-		"""Pretty print the tag information
-
-		The following format strings apply:
-		%%     Literal %
-		%n     Track number
-		%a     Artist
-		%t     Track title
-		%l     Album title
-		%y     Album release year
-		%g     Album genre"""
-		if not self._lock.acquire(block) and not block:
-			return False
-
-		esc = {'n': 'TRACKNUMBER',
-		       'a': 'ARTIST',
-			   't': 'TITLE',
-			   'l': 'ALBUM',
-			   'y': 'YEAR',
-			   'g': 'GENRE_NAME'}
-			  #'z': Used for literal '%'
-
-		out = ""
-		fmt = fmt.replace('%%', '%z')
-		fmt = fmt.split('%')
-		while fmt:
-			out += fmt[0] 
-			if len(fmt) <= 1: 
-				break
-			fmt = fmt[1:]
-			code = fmt[0] and fmt[0][0]
-			if code == 'z':
-				fmt[0] = '%' + fmt[0][1:]
-			elif code in esc.keys():
-				fmt[0] = self._tags.get(esc[code], ('',))[0] + fmt[0][1:]
-			else:
-				self._lock.release()
-				raise setup.ErrorBadFormat
-
-		self._lock.release()
-		return out
-
-
-	def __getitem__(self, key, block=True):
-
-		if not self._lock.acquire(block) and not block:
-			return False
-
-		if key == 'GENRE_NAME':
-			if not self._tags.has_key('GENRE'):
-				out = ''
-			else:
-				out = [genrenumbers.get(self._tags['GENRE'][0], self._tags['GENRE'][0])]
-		else:
-			try:
-				out = self._tags[key.upper()]
-			except KeyError:
-				self._lock.release()
-				raise
-				
-		self._lock.release()
-		return out
-
-
-	def __setitem__(self, key, value, block=True):
-
-		if not self._lock.acquire(block) and not block:
-			return False
-
-		if type(value) != type([]):
-			value = [value]
-		self._tags[key.upper()] = value
-
-		self._lock.release()
-		return True
-
-
-	def setorappend(self, key, value, block=True):
-		if not self._lock.acquire(block) and not block:
-			return False
-
-		key = key.upper()
-		if self._tags.has_key(key):
-			self._tags[key].append(value)
-		else:
-			self[key] = value
-
-		self._lock.release()
-		return True
-
-
-	def __delitem__(self, key, block=True):
-		if not self._lock.acquire(block) and not block:
-			return False
-
-		try:
-			del self._tags[key]
-		except KeyError:
-			self._lock.release()
-			raise	
-
-		self._lock.release()
-		return True
-
-
-	def keys(self, block=True):
-		if not self._lock.acquire(block) and not block:
-			return False
-
-		if self._tags.has_key('GENRE'):
-			out = self._tags.keys() + ['GENRE_NAME']
-		else:
-			out = self._tags.keys()
-
-		self._lock.release()
-		return out
-
+			raise setup.ErrorBadFormat
+
+	return out
 
 def remove_from_index(trackname, indexname):
 	"""Remove an entry from an index file."""

=== modified file 'mp3togo/track.py'
--- mp3togo/track.py	
+++ mp3togo/track.py	
@@ -24,6 +24,7 @@
 
 import mp3togo.conf as setup
 import mp3togo.tags as tags
+import audiotags
 import mp3togo.task as task
 import mp3togo.cache as cache
 import mp3togo.helpers 
@@ -82,8 +83,9 @@
 
 		# Read the tags
 		# Do this early so that 'treestructure' can access them
-		self.tags = tags.Tags(filename)
-		self.tags.read()
+		self.tags = audiotags.AudioFile(filename)
+		if not audiotags.supported(self.tags):
+			raise setup.UnknownFileType(filename)
 
 		# Names 
 		filetype = setup.getfiletype(filename)
@@ -93,9 +95,9 @@
 		base = opts.cleanfilename(base)
 		if opts['treestructure'] != '':
 			# Standard format string
-			# See tags.Tags.format.__doc__
+			# See tags.format.__doc__
 			fmt = opts['treestructure']
-			dest = self.tags.format(fmt)
+			dest = tags.format(self.tags, fmt)
 
 			self._outdir = os.path.dirname(dest)
 			self._outdir = os.path.join(opts['playerdir'], self._outdir)
@@ -215,10 +217,10 @@
 		if opts['index']:
 			indexname = os.path.join(self._outdir, '2go.index')
 			def undo_index():
-				tags.remove_from_index(self._outname, indexname)
+				tags.remove_from_index(self.tags, self._outname, indexname)
 				return True
 			def write_index():
-				self.tags.writeindex(self._outname, indexname)
+				tags.writeindex(self.tags, self._outname, indexname)
 				return True
 			job = task.SimpleTask(self, write_index, None,
 								  undo_index, name='Writing index')
@@ -229,7 +231,12 @@
 		# tag files from the cache as well, brwarning may have changed
 		if not opts['notags']:
 			def tag_output():
-				self.tags.write(self._outname)
+				outfile = audiotags.AudioFile(self._outname)
+				if not audiotags.supported(outfile):
+					raise setup.UnknownFileType(self._outname)
+				for k in self.tags.realkeys():
+					outfile.add(k, self.tags[k])
+				outfile.write()
 				return True
 			job = task.SimpleTask(self, tag_output, None, 
 			                      lambda: True, name="Tagging")
@@ -283,5 +290,3 @@
 		for child in self._queue:
 			child._parent = None
 		self._queue = ()
-
-	



More information about the mp3togo mailing list