1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
# This file implements a class which forms an interface to the .cddb
# directory that is maintained by SGI's cdman program.
#
# Usage is as follows:
#
# import readcd
# r = readcd.Readcd()
# c = Cddb(r.gettrackinfo())
#
# Now you can use c.artist, c.title and c.track[trackno] (where trackno
# starts at 1). When the CD is not recognized, all values will be the empty
# string.
# It is also possible to set the above mentioned variables to new values.
# You can then use c.write() to write out the changed values to the
# .cdplayerrc file.
import string, posix, os
_cddbrc = '.cddb'
_DB_ID_NTRACKS = 5
_dbid_map = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@_=+abcdefghijklmnopqrstuvwxyz'
def _dbid(v):
if v >= len(_dbid_map):
return string.zfill(v, 2)
else:
return _dbid_map[v]
def tochash(toc):
if type(toc) == type(''):
tracklist = []
for i in range(2, len(toc), 4):
tracklist.append((None,
(int(toc[i:i+2]),
int(toc[i+2:i+4]))))
else:
tracklist = toc
ntracks = len(tracklist)
hash = _dbid((ntracks >> 4) & 0xF) + _dbid(ntracks & 0xF)
if ntracks <= _DB_ID_NTRACKS:
nidtracks = ntracks
else:
nidtracks = _DB_ID_NTRACKS - 1
min = 0
sec = 0
for track in tracklist:
start, length = track
min = min + length[0]
sec = sec + length[1]
min = min + sec / 60
sec = sec % 60
hash = hash + _dbid(min) + _dbid(sec)
for i in range(nidtracks):
start, length = tracklist[i]
hash = hash + _dbid(length[0]) + _dbid(length[1])
return hash
class Cddb:
def __init__(self, tracklist):
if os.environ.has_key('CDDB_PATH'):
path = os.environ['CDDB_PATH']
cddb_path = path.split(',')
else:
home = os.environ['HOME']
cddb_path = [home + '/' + _cddbrc]
self._get_id(tracklist)
for dir in cddb_path:
file = dir + '/' + self.id + '.rdb'
try:
f = open(file, 'r')
self.file = file
break
except IOError:
pass
ntracks = int(self.id[:2], 16)
self.artist = ''
self.title = ''
self.track = [None] + [''] * ntracks
self.trackartist = [None] + [''] * ntracks
self.notes = []
if not hasattr(self, 'file'):
return
import re
reg = re.compile(r'^([^.]*)\.([^:]*):[\t ]+(.*)')
while 1:
line = f.readline()
if not line:
break
match = reg.match(line)
if not match:
print 'syntax error in ' + file
continue
name1, name2, value = match.group(1, 2, 3)
if name1 == 'album':
if name2 == 'artist':
self.artist = value
elif name2 == 'title':
self.title = value
elif name2 == 'toc':
if not self.toc:
self.toc = value
if self.toc != value:
print 'toc\'s don\'t match'
elif name2 == 'notes':
self.notes.append(value)
elif name1[:5] == 'track':
try:
trackno = int(name1[5:])
except strings.atoi_error:
print 'syntax error in ' + file
continue
if trackno > ntracks:
print 'track number ' + `trackno` + \
' in file ' + file + \
' out of range'
continue
if name2 == 'title':
self.track[trackno] = value
elif name2 == 'artist':
self.trackartist[trackno] = value
f.close()
for i in range(2, len(self.track)):
track = self.track[i]
# if track title starts with `,', use initial part
# of previous track's title
if track and track[0] == ',':
try:
off = self.track[i - 1].index(',')
except ValueError:
pass
else:
self.track[i] = self.track[i-1][:off] \
+ track
def _get_id(self, tracklist):
# fill in self.id and self.toc.
# if the argument is a string ending in .rdb, the part
# upto the suffix is taken as the id.
if type(tracklist) == type(''):
if tracklist[-4:] == '.rdb':
self.id = tracklist[:-4]
self.toc = ''
return
t = []
for i in range(2, len(tracklist), 4):
t.append((None, \
(int(tracklist[i:i+2]), \
int(tracklist[i+2:i+4]))))
tracklist = t
ntracks = len(tracklist)
self.id = _dbid((ntracks >> 4) & 0xF) + _dbid(ntracks & 0xF)
if ntracks <= _DB_ID_NTRACKS:
nidtracks = ntracks
else:
nidtracks = _DB_ID_NTRACKS - 1
min = 0
sec = 0
for track in tracklist:
start, length = track
min = min + length[0]
sec = sec + length[1]
min = min + sec / 60
sec = sec % 60
self.id = self.id + _dbid(min) + _dbid(sec)
for i in range(nidtracks):
start, length = tracklist[i]
self.id = self.id + _dbid(length[0]) + _dbid(length[1])
self.toc = string.zfill(ntracks, 2)
for track in tracklist:
start, length = track
self.toc = self.toc + string.zfill(length[0], 2) + \
string.zfill(length[1], 2)
def write(self):
import posixpath
if os.environ.has_key('CDDB_WRITE_DIR'):
dir = os.environ['CDDB_WRITE_DIR']
else:
dir = os.environ['HOME'] + '/' + _cddbrc
file = dir + '/' + self.id + '.rdb'
if posixpath.exists(file):
# make backup copy
posix.rename(file, file + '~')
f = open(file, 'w')
f.write('album.title:\t' + self.title + '\n')
f.write('album.artist:\t' + self.artist + '\n')
f.write('album.toc:\t' + self.toc + '\n')
for note in self.notes:
f.write('album.notes:\t' + note + '\n')
prevpref = None
for i in range(1, len(self.track)):
if self.trackartist[i]:
f.write('track'+`i`+'.artist:\t'+self.trackartist[i]+'\n')
track = self.track[i]
try:
off = track.index(',')
except ValuError:
prevpref = None
else:
if prevpref and track[:off] == prevpref:
track = track[off:]
else:
prevpref = track[:off]
f.write('track' + `i` + '.title:\t' + track + '\n')
f.close()
|