Package amplee :: Package atompub :: Package member :: Module audio
[hide private]
[frames] | no frames]

Source Code for Module amplee.atompub.member.audio

  1  # -*- coding: utf-8 -*- 
  2   
  3  __doc__ = """ 
  4  This module defines a set of member classes aiming at 
  5  dealing with audio formats such as Vorbis, Flac, MP3, WMA, etc. 
  6   
  7  This classes will generate an entry member based on the id3 tags 
  8  of media resources. This means that you should be careful on 
  9  how those are set before using these classes. 
 10   
 11  This package will require the mutagen library that your can find at: 
 12  http://cheeseshop.python.org/pypi/mutagen/ 
 13   
 14  And wmainfo for WMA support: 
 15  http://cheeseshop.python.org/pypi/wmainfo-py 
 16  """ 
 17   
 18  from datetime import datetime 
 19  import os 
 20  from xml.sax.saxutils import escape 
 21   
 22  from bridge import Element, Attribute 
 23  from bridge.lib import isodate 
 24  from bridge.common import ATOM10_PREFIX, ATOMPUB_PREFIX, XML_PREFIX, XML_NS, \ 
 25       ATOM10_NS, ATOMPUB_NS 
 26   
 27  from amplee.utils import generate_uuid_uri, parse_isodate, get_isodate 
 28  from amplee.utils import create_temporary_resource, delete_temporary_resource 
 29  from amplee.error import MemberMediaError 
 30  from amplee.atompub.member import MediaMember 
 31  from amplee.atompub.member.helper import MemberHelper 
 32    
 33  from mutagen.easyid3 import EasyID3 
 34  from mutagen.mp3 import MP3 
 35  from mutagen.oggvorbis import OggVorbis 
 36  from mutagen.oggflac import OggFLAC 
 37  from mutagen.flac import FLAC, FLACNoHeaderError 
 38  from mutagen.wavpack import WavPack 
 39  from mutagen.apev2 import APEv2File 
 40  from mutagen.m4a import M4A 
 41   
 42  try:            
 43       from wmainfo import WmaInfo 
 44  except ImportError: 
 45       from warnings import warn 
 46       warn("Couldn't import wmainfo.WmaInfo. WMA files will not be supported") 
 47       WmaInfo = None 
 48    
49 -class ID3BasedMember(MediaMember):
50 - def __init__(self, collection, source, audio, 51 ext, media_type, title=u'', description=u'', 52 name_format='%A %d %n', entry_id_creator=None, **kwargs):
53 """ 54 Creates a member based on ID3 tags, typically audio files such a MP3 or Vorbis 55 56 Keyword arguments 57 collection -- parent collection 58 source -- fileobject of content to handle 59 length -- amount of data to read from source 60 title -- title to use for the Atom entry. If not provided 61 will use 'title' ID3 tag. 62 description -- summary to use for the Atom entry 63 name_format -- template to generate the member and media ids 64 ext -- extension to use fo the media resource 65 media_type -- mime type of the media resource 66 entry_id_creator -- function object which will return the id 67 to use in the atom:id element (as an unicode object) 68 69 The name format defaults takes the following values: 70 %A -- artist name 71 %d -- album name 72 %t -- tracknumber 73 %n -- track title 74 %Y -- year 75 %M -- month 76 %D -- day 77 It defaults to %A %d %n 78 79 The entry_id_creator function must takes the following parameters: 80 base_uri, source, artist, album, tracknumber, title, date, genres 81 """ 82 MediaMember.__init__(self, collection, media_type=media_type) 83 84 if not name_format: 85 name_format = '%A %d %n' 86 87 artist, album, tracknumber, title, date, genres = self._get_infos(audio) 88 name_format = name_format.replace('%A', artist) 89 name_format = name_format.replace('%d', album) 90 name_format = name_format.replace('%t', tracknumber) 91 name_format = name_format.replace('%n', title) 92 name_format = name_format.replace('%Y', str(date.year)) 93 name_format = name_format.replace('%M', "%02d" % date.month) 94 name_format = name_format.replace('%D', "%02d" % date.day) 95 96 media_id = member_id = name_format 97 if ext: 98 media_id = u'%s.%s' % (media_id, ext) 99 if self.collection.member_extension: 100 member_id = u'%s.%s.%s' % (member_id, ext, self.collection.member_extension) 101 102 self.media_id = media_id 103 self.member_id = member_id 104 105 if callable(entry_id_creator): 106 id = entry_id_creator(self.collection.base_uri, source, 107 artist, album, tracknumber, title, date, genres) 108 else: 109 id = generate_uuid_uri() 110 111 mh = MemberHelper(self.collection) 112 mh.initiate(id=id) 113 mh.add_element('title', content=title, attributes={u'type': u'text'}) 114 mh.add_element('summary', unicode(description), attributes={u'type': u'text'}) 115 author = mh.add_element('author') 116 mh.add_element('name', content=unicode(artist), parent=author) 117 attr = {u'rel': u'edit', u'type': self.collection.member_media_type, 118 u'href': unicode(escape("%s/%s" % (self.collection.base_edit_uri, 119 member_id))),} 120 mh.add_element('link', attributes=attr) 121 122 attr = {u'rel': u'edit-media', u'type': self.media_type, 123 u'href': unicode(escape("%s/%s" % (self.collection.base_media_edit_uri, 124 media_id)))} 125 link = mh.add_element('link', attributes=attr) 126 127 for genre in genres: 128 mh.add_element(u'category', attributes={u'term': unicode(genre)}) 129 130 attr = {u'src': unicode(escape("%s/%s" % (self.collection.base_uri, media_id))), 131 u'type': self.media_type} 132 mh.add_element('content', attributes=attr) 133 134 self.entry = mh.entry 135 del mh
136
137 - def _get_infos(self, audio):
138 artist = u'' 139 if 'artist' in audio: 140 artist = audio['artist'].pop() 141 142 album = u'' 143 if 'album' in audio: 144 album = audio['album'].pop() 145 146 title = u'' 147 if 'title' in audio: 148 title = audio['title'].pop() 149 150 tracknumber = u'' 151 if 'tracknumber' in audio: 152 tracknumber = audio['tracknumber'].pop() 153 154 date = None 155 if 'date' in audio: 156 date = parse_isodate(audio['date'].pop()) 157 if not date: 158 date = get_isodate() 159 160 genres = [] 161 if 'genre' in audio: 162 genres = audio['genre'] 163 164 return artist, album, tracknumber, title, date, genres
165
166 -class MP3Member(ID3BasedMember):
167 - def __init__(self, collection, source, 168 title=u'', description=u'', 169 name_format=None, ext='mp3', 170 media_type=u'audio/mpeg', 171 entry_id_creator=None, **kwargs):
172 fd, path, content = create_temporary_resource(source) 173 audio = MP3(path, ID3=EasyID3) 174 ID3BasedMember.__init__(self, collection, path, audio, 175 title=title, description=description, 176 name_format=name_format, ext=ext, media_type=media_type, 177 entry_id_creator=entry_id_creator, **kwargs) 178 delete_temporary_resource(path)
179 180
181 -class OGGMember(ID3BasedMember):
182 - def __init__(self, collection, source, 183 title=u'', description=u'', 184 name_format=None, ext='ogg', 185 media_type=u'application/ogg', 186 entry_id_creator=None, **kwargs):
187 fd, path, content = create_temporary_resource(source) 188 audio = OggVorbis(path) 189 ID3BasedMember.__init__(self, collection, path, audio, 190 title=title, description=description, 191 name_format=name_format, ext=ext, media_type=media_type, 192 entry_id_creator=entry_id_creator, **kwargs) 193 delete_temporary_resource(path)
194
195 -class FlacMember(ID3BasedMember):
196 - def __init__(self, collection, source, 197 title=u'', description=u'', 198 name_format=None, ext='flac', 199 media_type=u'audio/x-flac', 200 entry_id_creator=None, **kwargs):
201 fd, path, content = create_temporary_resource(source) 202 try: 203 audio = FLAC(path) 204 except FLACNoHeaderError: 205 try: 206 audio = OggFLAC(path) 207 except: 208 raise 209 ID3BasedMember.__init__(self, collection, path, audio, 210 title=title, description=description, 211 name_format=name_format, ext=ext, media_type=media_type, 212 entry_id_creator=entry_id_creator, **kwargs) 213 delete_temporary_resource(path)
214
215 -class WavPackMember(ID3BasedMember):
216 - def __init__(self, collection, source, 217 title=u'', description=u'', 218 name_format=None, ext='wv', 219 media_type=u'audio/x-wav', 220 entry_id_creator=None, **kwargs):
221 fd, path, content = create_temporary_resource(source) 222 audio = APEv2File(path) 223 ID3BasedMember.__init__(self, collection, path, audio, 224 title=title, description=description, 225 name_format=name_format, ext=ext, media_type=media_type, 226 entry_id_creator=entry_id_creator, **kwargs) 227 delete_temporary_resource(path)
228
229 - def _get_infos(self, audio):
230 artist = u'' 231 if 'Artist' in audio: 232 artist = unicode(audio['Artist'].value) 233 234 album = u'' 235 if 'Album' in audio: 236 album = unicode(audio['Album'].value) 237 238 title = u'' 239 if 'Title' in audio: 240 title = unicode(audio['Title'].value) 241 242 date = None 243 if 'Date' in audio: 244 date = parse_isodate(audio['Date'].value) 245 if not date: 246 date = datetime.now() 247 248 tracknumber = u'' 249 if 'Track' in audio: 250 tracknumber = unicode(audio['Track'].value) 251 252 return artist, album, tracknumber, title, date, []
253 254
255 -class M4AMember(ID3BasedMember):
256 - def __init__(self, collection, source, 257 title=u'', description=u'', 258 name_format=None, ext='m4a', 259 media_type=u'audio/mp4a', 260 entry_id_creator=None, **kwargs):
261 fd, path, content = create_temporary_resource(source) 262 audio = M4A(path) 263 ID3BasedMember.__init__(self, collection, path, audio, 264 title=title, description=description, 265 name_format=name_format, ext=ext, media_type=media_type, 266 entry_id_creator=entry_id_creator, **kwargs) 267 delete_temporary_resource(path)
268
269 - def _get_infos(self, audio):
270 artist = u'' 271 if '\xa9ART' in audio: 272 artist = audio['\xa9ART'] 273 274 album = u'' 275 if '\xa9alb' in audio: 276 album = audio['\xa9alb'] 277 278 title = u'' 279 if '\xa9nam' in audio: 280 title = audio['\xa9nam'] 281 282 tracknumber = u'' 283 if 'tracknumber' in audio: 284 tracknumber = [str(digit) for digit in audio['trkn']] 285 tracknumber.reverse() 286 tracknumber = ''.join(tracknumber) 287 288 genres = [] 289 if '\xa9gen' in audio: 290 genres = audio['\xa9gen'] 291 292 date = datetime.now() 293 294 return artist, album, tracknumber, title, date, genres
295 296 297 if WmaInfo:
298 - class WMAMember(ID3BasedMember):
299 - def __init__(self, collection, source, 300 title=u'', description=u'', 301 name_format=None, ext='wma', 302 media_type=u'audio/x-ms-wma', 303 entry_id_creator=None, **kwargs):
304 fd, path, content = create_temporary_resource(source) 305 audio = WmaInfo(path) 306 ID3BasedMember.__init__(self, collection, path, audio, 307 title=title, description=description, 308 name_format=name_format, ext=ext, media_type=media_type, 309 entry_id_creator=entry_id_creator, **kwargs) 310 delete_temporary_resource(path)
311
312 - def _get_infos(self, audio):
313 artist = unicode(audio.tags.get('Author', '')) 314 title = unicode(audio.tags.get('Title', '')) 315 tracknumber = unicode(audio.tags.get('TrackNumber', '')) 316 album = unicode(audio.tags.get('AlbumTitle', '')) 317 genres = [unicode(audio.tags.get('Genre', ''))] 318 date = audio.tags.get('Year', '') 319 date = parse_isodate(date) 320 if not date: 321 date = datetime.now() 322 323 return artist, album, tracknumber, title, date, genres
324