blob: 0dee709849f1c53898d5727eec4c7d75292bc839 [file] [log] [blame]
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +00001# This file implements a class which forms an interface to the .cddb
2# directory that is maintained by SGI's cdman program.
3#
4# Usage is as follows:
5#
6# import readcd
Sjoerd Mullenderb2e358d1993-11-08 15:10:43 +00007# r = readcd.Readcd()
8# c = Cddb(r.gettrackinfo())
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +00009#
10# Now you can use c.artist, c.title and c.track[trackno] (where trackno
11# starts at 1). When the CD is not recognized, all values will be the empty
12# string.
13# It is also possible to set the above mentioned variables to new values.
14# You can then use c.write() to write out the changed values to the
15# .cdplayerrc file.
16
Sjoerd Mullenderc9d73d11993-09-27 12:36:01 +000017import string, posix
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +000018
Sjoerd Mullenderc9d73d11993-09-27 12:36:01 +000019_cddbrc = '.cddb'
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +000020_DB_ID_NTRACKS = 5
21_dbid_map = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@_=+abcdefghijklmnopqrstuvwxyz'
22def _dbid(v):
23 if v >= len(_dbid_map):
24 return string.zfill(v, 2)
25 else:
26 return _dbid_map[v]
27
Sjoerd Mullenderc9d73d11993-09-27 12:36:01 +000028def tochash(toc):
29 if type(toc) == type(''):
30 tracklist = []
31 for i in range(2, len(toc), 4):
32 tracklist.append((None,
33 (string.atoi(toc[i:i+2]),
34 string.atoi(toc[i+2:i+4]))))
35 else:
36 tracklist = toc
37 ntracks = len(tracklist)
38 hash = _dbid((ntracks >> 4) & 0xF) + _dbid(ntracks & 0xF)
39 if ntracks <= _DB_ID_NTRACKS:
40 nidtracks = ntracks
41 else:
42 nidtracks = _DB_ID_NTRACKS - 1
43 min = 0
44 sec = 0
45 for track in tracklist:
46 start, length = track
47 min = min + length[0]
48 sec = sec + length[1]
49 min = min + sec / 60
50 sec = sec % 60
51 hash = hash + _dbid(min) + _dbid(sec)
52 for i in range(nidtracks):
53 start, length = tracklist[i]
54 hash = hash + _dbid(length[0]) + _dbid(length[1])
55 return hash
56
Guido van Rossumd3166071993-05-24 14:16:22 +000057class Cddb:
Sjoerd Mullenderb2e358d1993-11-08 15:10:43 +000058 def __init__(self, tracklist):
Sjoerd Mullenderc9d73d11993-09-27 12:36:01 +000059 if posix.environ.has_key('CDDB_PATH'):
60 path = posix.environ['CDDB_PATH']
61 cddb_path = string.splitfields(path, ',')
62 else:
63 home = posix.environ['HOME']
64 cddb_path = [home + '/' + _cddbrc]
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +000065 self.artist = ''
66 self.title = ''
67 if type(tracklist) == type(''):
68 t = []
69 for i in range(2, len(tracklist), 4):
70 t.append((None, \
71 (string.atoi(tracklist[i:i+2]), \
72 string.atoi(tracklist[i+2:i+4]))))
73 tracklist = t
74 ntracks = len(tracklist)
75 self.track = [None] + [''] * ntracks
76 self.id = _dbid((ntracks >> 4) & 0xF) + _dbid(ntracks & 0xF)
77 if ntracks <= _DB_ID_NTRACKS:
78 nidtracks = ntracks
79 else:
80 nidtracks = _DB_ID_NTRACKS - 1
81 min = 0
82 sec = 0
83 for track in tracklist:
84 start, length = track
85 min = min + length[0]
86 sec = sec + length[1]
87 min = min + sec / 60
88 sec = sec % 60
89 self.id = self.id + _dbid(min) + _dbid(sec)
90 for i in range(nidtracks):
91 start, length = tracklist[i]
92 self.id = self.id + _dbid(length[0]) + _dbid(length[1])
93 self.toc = string.zfill(ntracks, 2)
94 for track in tracklist:
95 start, length = track
96 self.toc = self.toc + string.zfill(length[0], 2) + \
97 string.zfill(length[1], 2)
Sjoerd Mullenderc9d73d11993-09-27 12:36:01 +000098 for dir in cddb_path:
99 file = dir + '/' + self.id + '.rdb'
100 try:
101 f = open(file, 'r')
102 self.file = file
103 break
104 except IOError:
105 pass
106 if not hasattr(self, 'file'):
Sjoerd Mullenderb2e358d1993-11-08 15:10:43 +0000107 return
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000108 import regex
109 reg = regex.compile('^\\([^.]*\\)\\.\\([^:]*\\):\t\\(.*\\)')
110 while 1:
111 line = f.readline()
112 if not line:
113 break
114 if reg.match(line) == -1:
115 print 'syntax error in ' + file
116 continue
117 name1 = line[reg.regs[1][0]:reg.regs[1][1]]
118 name2 = line[reg.regs[2][0]:reg.regs[2][1]]
119 value = line[reg.regs[3][0]:reg.regs[3][1]]
120 if name1 == 'album':
121 if name2 == 'artist':
122 self.artist = value
123 elif name2 == 'title':
124 self.title = value
125 elif name2 == 'toc':
126 if self.toc != value:
127 print 'toc\'s don\'t match'
128 elif name1[:5] == 'track':
Sjoerd Mullender8562c4c1993-03-29 10:49:59 +0000129 try:
130 trackno = string.atoi(name1[5:])
131 except strings.atoi_error:
132 print 'syntax error in ' + file
133 continue
134 if trackno > ntracks:
Sjoerd Mullenderc9d73d11993-09-27 12:36:01 +0000135 print 'track number ' + `trackno` + \
Sjoerd Mullender8562c4c1993-03-29 10:49:59 +0000136 ' in file ' + file + \
137 ' out of range'
138 continue
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000139 self.track[trackno] = value
140 f.close()
Guido van Rossumb6775db1994-08-01 11:34:53 +0000141 for i in range(2, len(self.track)):
142 track = self.track[i]
143 # if track title starts with `,', use initial part
144 # of previous track's title
145 if track[0] == ',':
146 try:
147 off = string.index(self.track[i - 1],
148 ',')
149 except string.index_error:
150 pass
151 else:
152 self.track[i] = self.track[i-1][:off] \
153 + track
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000154
155 def write(self):
Sjoerd Mullenderb2e358d1993-11-08 15:10:43 +0000156 import posixpath
Sjoerd Mullenderc9d73d11993-09-27 12:36:01 +0000157 if posix.environ.has_key('CDDB_WRITE_DIR'):
158 dir = posix.environ['CDDB_WRITE_DIR']
159 else:
160 dir = posix.environ['HOME'] + '/' + _cddbrc
161 file = dir + '/' + self.id + '.rdb'
Sjoerd Mullenderb2e358d1993-11-08 15:10:43 +0000162 if posixpath.exists(file):
163 # make backup copy
164 posix.rename(file, file + '~')
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000165 f = open(file, 'w')
166 f.write('album.title:\t' + self.title + '\n')
167 f.write('album.artist:\t' + self.artist + '\n')
168 f.write('album.toc:\t' + self.toc + '\n')
Guido van Rossumb6775db1994-08-01 11:34:53 +0000169 prevpref = None
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000170 for i in range(1, len(self.track)):
Guido van Rossumb6775db1994-08-01 11:34:53 +0000171 track = self.track[i]
172 try:
173 off = string.index(track, ',')
174 except string.index_error:
175 prevpref = None
176 else:
177 if prevpref and track[:off] == prevpref:
178 track = track[off:]
179 else:
180 prevpref = track[:off]
181 f.write('track' + `i` + '.title:\t' + track + '\n')
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000182 f.close()