Initial Commit
[Projects.git] / pkgbuilds / pytivo / pkg / usr / share / pyTivo / mutagen / __init__.py
blob844d587bfa09209b788ccc3d73a0c12b296c742d
1 #! /usr/bin/env python
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 4348 2008-12-02 02:41:15Z 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.
22 """
24 version = (1, 15)
25 version_string = ".".join(map(str, version))
27 import warnings
29 import mutagen._util
31 class Metadata(object):
32 """An abstract dict-like object.
34 Metadata is the base class for many of the tag objects in Mutagen.
35 """
37 def __init__(self, *args, **kwargs):
38 if args or 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.
53 Attributes:
54 info -- stream information (length, bitrate, sample rate)
55 tags -- metadata tags, if any
57 Each file format has different potential tags and stream
58 information.
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.
63 """
65 info = None
66 tags = None
67 filename = None
68 _mimes = ["application/octet-stream"]
70 def __init__(self, filename=None, *args, **kwargs):
71 if filename is None:
72 warnings.warn("FileType constructor requires a filename",
73 DeprecationWarning)
74 else:
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.
84 """
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).
93 """
94 if self.tags is None:
95 self.add_tags()
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])
106 def keys(self):
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:
117 if filename is None:
118 filename = self.filename
119 else:
120 warnings.warn(
121 "delete(filename=...) is deprecated, reload the file",
122 DeprecationWarning)
123 return self.tags.delete(filename)
125 def save(self, filename=None, **kwargs):
126 """Save metadata tags."""
127 if filename is None:
128 filename = self.filename
129 else:
130 warnings.warn(
131 "save(filename=...) is deprecated, reload the file",
132 DeprecationWarning)
133 if self.tags is not None:
134 return self.tags.save(filename, **kwargs)
135 else: raise ValueError("no tags in file")
137 def pprint(self):
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:
142 return stream
143 else: return stream + ((tags and "\n" + tags) or "")
145 def add_tags(self):
146 raise NotImplementedError
148 def __get_mime(self):
149 mimes = []
150 for Kind in type(self).__mro__:
151 for mime in getattr(Kind, '_mimes', []):
152 if mime not in mimes:
153 mimes.append(mime)
154 return 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.
168 if options is None:
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]
188 if not options:
189 return None
191 fileobj = file(filename, "rb")
192 try:
193 header = fileobj.read(128)
194 # Sort by name after score. Otherwise import order affects
195 # Kind sort order, which affects treatment of things with
196 # equals scores.
197 results = [(Kind.score(filename, fileobj, header), Kind.__name__)
198 for Kind in options]
199 finally:
200 fileobj.close()
201 results = zip(results, options)
202 results.sort()
203 (score, name), Kind = results[-1]
204 if score > 0: return Kind(filename)
205 else: return None