/[soapbox]/prolatio/music_tagger/tagging.py
ViewVC logotype

Contents of /prolatio/music_tagger/tagging.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3028 - (show annotations) (download) (as text)
Sun Sep 5 13:38:08 2010 UTC (11 years, 8 months ago) by tadas
File MIME type: text/x-python
File size: 5098 byte(s)
Music library/music e-shop based on django and satchmo
1 import tagpy
2
3 class TagExtBase(object):
4 def __init__(self, tag, map):
5 # bypass __setattr__
6 self.__dict__['tag'] = tag
7 self.__dict__['map'] = map
8
9 # a shortcut for getting values from field map
10 def map_get(self, key, default=None):
11 try:
12 el = self.map[key]
13 except:
14 return default
15 if type(el).__name__ == 'StringList':
16 return el[0]
17 return el
18
19 class TagExtXiph(TagExtBase):
20 # used XiphComment fields are: COMPOSER, CONDUCTOR, COPYRIGHT, DISCNUMBER, DISCTOTAL, TRACKTOTAL
21
22 def __init__(self, tag):
23 super(TagExtXiph, self).__init__(tag, tag.fieldListMap())
24
25 # map internal field names to XiphComment fields and return conversion functions (if needed)
26 def field_map(self, field):
27 if field == 'disc':
28 return ('DISCNUMBER', int)
29 if field == 'disc_count':
30 return ('DISCTOTAL', int)
31 if field == 'track_count':
32 return ('TRACKTOTAL', int)
33 # just uppercase composer, conductor and copyright
34 return (str(field).upper(), None)
35
36 def __getattr__(self, name):
37 (field, conversion) = self.field_map(name)
38 value = self.map_get(field)
39 if callable(conversion) and value != None:
40 value = conversion.__call__(value)
41 return value
42
43 def __setattr__(self, name, value):
44 field = self.field_map(name)[0]
45 self.tag.addField(field, unicode(value), True)
46
47 class TagExtID3v2(TagExtBase):
48 def __init__(self, tag):
49 super(TagExtID3v2, self).__init__(tag, tag.frameListMap())
50
51 def __getattr__(self, name):
52 pass
53
54 def __setattr__(self, name, value):
55 pass
56
57 class TagExtAPE(TagExtBase):
58 def __init__(self, tag):
59 super(TagExtAPE, self).__init__(tag, tag.itemListMap())
60
61 def __getattr__(self, name):
62 pass
63
64 def __setattr__(self, name, value):
65 pass
66
67 # a wrapper around TagPy to seamlessly handle non-standard tags
68 # specific tag handling implementation is based on the excellent taglib-sharp
69 class MetaFile(object):
70 TAG_COMMON_ATTRS = ('album', 'artist', 'comment', 'genre', 'title', 'track', 'year')
71 TAG_EXT_ATTRS = ('composer', 'conductor', 'copyright', 'disc', 'disc_count', 'track_count')
72 AUDIOPROP_COMMON_ATTRS = ('bitrate', 'channels', 'length', 'sampleRate')
73
74 def __init__(self, file, readAudioProperties=True, audioPropertiesStyle=tagpy.ReadStyle.Average):
75 fileref = tagpy.FileRef(file, readAudioProperties, audioPropertiesStyle)
76 # set main attrs (bypassing __setattr__)
77 dict = self.__dict__
78 dict['f'] = fileref.file()
79 dict['tag'] = self.f.tag()
80 dict['tag_ext'] = MetaFile.get_ext_tag(self.f)
81 dict['audioprops'] = dict['f'].audioProperties()
82
83 @staticmethod
84 def get_ext_tag(file):
85 def by_tag_class(tag):
86 tag_type = tag.__class__.__name__
87 if tag_type == 'ogg_XiphComment':
88 return TagExtXiph(tag)
89 if tag_type == 'id3v2_Tag':
90 return TagExtID3v2(tag)
91 if tag_type == 'ape_Tag':
92 return TagExtAPE(tag)
93
94 # choose most preferrable tag type where we have choice
95 # don't consider ID3v1 since it's not possible to add any non-standard tags to it
96 file_type = file.__class__.__name__
97 if file_type == 'flac_File':
98 tag_xiph = file.xiphComment()
99 tag_id3v2 = file.ID3v2Tag()
100 return by_tag_class(tag_xiph or tag_id3v2 or file.xiphComment(create=True))
101 if file_type == 'mpc_File':
102 tag_ape = file.APETag()
103 tag_id3v1 = file.ID3v2Tag()
104 return by_tag_class(tag_ape or tag_id3v1 or file.APETag(create=True))
105 if file_type == 'mpeg_File':
106 tag_ape = file.APETag()
107 tag_id3v2 = file.ID3v2Tag()
108 return by_tag_class(tag_ape or tag_id3v2 or file.APETag(create=True))
109 # if file_type == 'trueaudio_File':
110 # tag_id3v2 = file.ID3v2Tag(create=True)
111 # return by_tag_class(tag_id3v2)
112 # if file_type == 'wavpack_File':
113 # tag_ape = file.APETag(create=True)
114 # return by_tag_class(tag_ape)
115 # get default tag type
116 return by_tag_class(file.tag())
117
118 def __getattr__(self, name):
119 if name in MetaFile.TAG_COMMON_ATTRS:
120 return getattr(self.tag, name)
121 if name in MetaFile.TAG_EXT_ATTRS:
122 return getattr(self.tag_ext, name)
123 if name in MetaFile.AUDIOPROP_COMMON_ATTRS:
124 return getattr(self.audioprops, name)
125
126 def __setattr__(self, name, value):
127 if name in MetaFile.TAG_COMMON_ATTRS:
128 setattr(self.tag, name, value)
129 elif name in MetaFile.TAG_EXT_ATTRS:
130 setattr(self.tag_ext, name, value)
131
132 def save(self):
133 self.f.save()

tadas_AT_dailyda_DOT_com
ViewVC Help
Powered by ViewVC 1.1.8