3 # mutagen aims to be an all purpose media tagging library
4 # Copyright (C) 2005 Michael Urman
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of version 2 of the GNU General Public License as
8 # published by the Free Software Foundation.
10 # $Id: __init__.py 4275 2008-06-01 06:32:37Z piman $
13 """Mutagen aims to be an all purpose tagging library.
15 import mutagen.[format]
16 metadata = mutagen.[format].Open(filename)
18 metadata acts like a dictionary of tags in the file. Tags are generally a
19 list of string-like values, but may have additional methods available
20 depending on tag or format. They may also be entirely different objects
21 for certain keys, again depending on format.
25 version_string = ".".join(map(str, version))
31 class Metadata(object):
32 """An abstract dict-like object.
34 Metadata is the base class for many of the tag objects in Mutagen.
37 def __init__(self, *args, **kwargs):
39 self.load(*args, **kwargs)
41 def load(self, *args, **kwargs):
42 raise NotImplementedError
44 def save(self, filename=None):
45 raise NotImplementedError
47 def delete(self, filename=None):
48 raise NotImplementedError
50 class FileType(mutagen._util.DictMixin):
51 """An abstract object wrapping tags and audio stream information.
54 info -- stream information (length, bitrate, sample rate)
55 tags -- metadata tags, if any
57 Each file format has different potential tags and stream
60 FileTypes implement an interface very similar to Metadata; the
61 dict interface, save, load, and delete calls on a FileType call
62 the appropriate methods on its tag data.
68 _mimes = ["application/octet-stream"]
70 def __init__(self, filename=None, *args, **kwargs):
72 warnings.warn("FileType constructor requires a filename",
75 self.load(filename, *args, **kwargs)
77 def load(self, filename, *args, **kwargs):
78 raise NotImplementedError
80 def __getitem__(self, key):
81 """Look up a metadata tag key.
83 If the file has no tags at all, a KeyError is raised.
85 if self.tags is None: raise KeyError, key
86 else: return self.tags[key]
88 def __setitem__(self, key, value):
89 """Set a metadata tag.
91 If the file has no tags, an appropriate format is added (but
92 not written until save is called).
96 self.tags[key] = value
98 def __delitem__(self, key):
99 """Delete a metadata tag key.
101 If the file has no tags at all, a KeyError is raised.
103 if self.tags is None: raise KeyError, key
104 else: del(self.tags[key])
107 """Return a list of keys in the metadata tag.
109 If the file has no tags at all, an empty list is returned.
111 if self.tags is None: return []
112 else: return self.tags.keys()
114 def delete(self, filename=None):
115 """Remove tags from a file."""
116 if self.tags is not None:
118 filename = self.filename
121 "delete(filename=...) is deprecated, reload the file",
123 return self.tags.delete(filename)
125 def save(self, filename=None, **kwargs):
126 """Save metadata tags."""
128 filename = self.filename
131 "save(filename=...) is deprecated, reload the file",
133 if self.tags is not None:
134 return self.tags.save(filename, **kwargs)
135 else: raise ValueError("no tags in file")
138 """Print stream information and comment key=value pairs."""
139 stream = "%s (%s)" % (self.info.pprint(), self.mime[0])
140 try: tags = self.tags.pprint()
141 except AttributeError:
143 else: return stream + ((tags and "\n" + tags) or "")
146 raise NotImplementedError
148 def __get_mime(self):
150 for Kind in type(self).__mro__:
151 for mime in getattr(Kind, '_mimes', []):
152 if mime not in mimes:
156 mime = property(__get_mime)
158 def File(filename, options=None):
159 """Guess the type of the file and try to open it.
161 The file type is decided by several things, such as the first 128
162 bytes (which usually contains a file type identifier), the
163 filename extension, and the presence of existing tags.
165 If no appropriate type could be found, None is returned.
169 from mutagen.asf import ASF
170 from mutagen.apev2 import APEv2File
171 from mutagen.flac import FLAC
172 from mutagen.id3 import ID3FileType
173 from mutagen.mp3 import MP3
174 from mutagen.oggflac import OggFLAC
175 from mutagen.oggspeex import OggSpeex
176 from mutagen.oggtheora import OggTheora
177 from mutagen.oggvorbis import OggVorbis
178 from mutagen.trueaudio import TrueAudio
179 from mutagen.wavpack import WavPack
180 from mutagen.mp4 import MP4
181 from mutagen.musepack import Musepack
182 from mutagen.monkeysaudio import MonkeysAudio
183 from mutagen.optimfrog import OptimFROG
184 options = [MP3, TrueAudio, OggTheora, OggSpeex, OggVorbis, OggFLAC,
185 FLAC, APEv2File, MP4, ID3FileType, WavPack, Musepack,
186 MonkeysAudio, OptimFROG, ASF]
191 fileobj = file(filename, "rb")
193 header = fileobj.read(128)
194 results = [Kind.score(filename, fileobj, header) for Kind in options]
197 results = zip(results, options)
199 score, Kind = results[-1]
200 if score > 0: return Kind(filename)