2 Copyright 2005 Kenneth Hayber <ken@hayber.us>, All rights reserved.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License.
8 This program is distributed in the hope that it will be useful
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 print 'No MP3 support!'
26 from pyid3lib
import *
31 print 'No id3v2 support'
34 ID3V2_GENRE_RE
= re
.compile('\((?P<genre>\d+)\)')
36 def to_unicode(s
, fallback_encoding
='iso-8859-1'):
38 return s
.decode('utf-8')
39 except UnicodeDecodeError:
40 return s
.decode(fallback_encoding
, 'ignore')
44 tag_info
= tag(song
.filename
)
47 tag_info
= ID3(song
.filename
)
51 for key
in ('title', 'track', 'album', 'artist', 'contenttype', 'genre'):
54 # it is a tuple (x of y)
56 val
= int(tag_info
.track
[0])
62 val
= to_unicode(getattr(tag_info
, key
))
63 if key
== 'contenttype':
65 # ID3v2 genres are either a string/tuple index
66 # e.g. '(17)' or the actual genre string.
67 x
= ID3V2_GENRE_RE
.match(val
)
69 val
= int(x
.group('genre'))
70 if key
== 'genre' and isinstance(val
, int):
71 val
= genres
.genre_list
[val
]
73 setattr(song
, key
, val
)
74 except (AttributeError, IndexError):
76 # don't trust any length specs from a tag
81 def __init__(self
, filename
, buffersize
):
82 """Initialize the decoder"""
83 self
.buffersize
= buffersize
84 self
.filename
= filename
87 """Open the file and prepare for decoding"""
88 self
.mf
= mad
.MadFile(self
.filename
) #, self.buffersize)
91 """Close the file and do any needed cleanup"""
95 """Return the length of the file in seconds as an integer"""
96 return self
.mf
.total_time()/1000
99 """Return the sample rate of the file in samples per second"""
100 return self
.mf
.samplerate()
103 """Return the number of channels in the file"""
104 if self
.mf
.mode() == mad
.MODE_SINGLE_CHANNEL
:
111 Read data from the file and decode to PCM data. Return a buffer
112 of data and length, or (None, 0) at EOF
114 buff
= self
.mf
.read()
116 return (buff
, len(buff
))
121 """Return the current playback position in seconds"""
122 return self
.mf
.current_time() / 1000
125 """Jump to pos as a percentage of the total length of the file"""
126 self
.mf
.seek_time(long(self
.length() * pos
* 1000))
129 """Display some MP3 information"""
130 if self
.mf
.layer() == mad
.LAYER_I
:
132 elif self
.mf
.layer() == mad
.LAYER_II
:
133 print "MPEG Layer II"
134 elif self
.mf
.layer() == mad
.LAYER_III
:
135 print "MPEG Layer III"
137 print "unexpected layer value"
139 if self
.mf
.mode() == mad
.MODE_SINGLE_CHANNEL
:
140 print "single channel"
141 elif self
.mf
.mode() == mad
.MODE_DUAL_CHANNEL
:
143 elif self
.mf
.mode() == mad
.MODE_JOINT_STEREO
:
144 print "joint (MS/intensity) stereo"
145 elif self
.mf
.mode() == mad
.MODE_STEREO
:
146 print "normal L/R stereo"
148 print "unexpected mode value"
150 if self
.mf
.emphasis() == mad
.EMPHASIS_NONE
:
152 elif self
.mf
.emphasis() == mad
.EMPHASIS_50_15_US
:
153 print "50/15us emphasis"
154 elif self
.mf
.emphasis() == mad
.EMPHASIS_CCITT_J_17
:
155 print "CCITT J.17 emphasis"
157 print "unexpected emphasis value"
159 print "bitrate %lu bps" % self
.mf
.bitrate()
160 print "samplerate %d Hz" % self
.mf
.samplerate()
161 millis
= self
.mf
.total_time()
163 print "total time %d ms (%dm%2ds)" % (millis
, secs
/ 60, secs
% 60)