blob: 68d26c0e7087471a5fe0c768f0d2831cd9d48cc4 [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 Mullendere202c381994-09-06 16:19:03 +000017import string, posix, os
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 Mullendere202c381994-09-06 16:19:03 +000059 if os.environ.has_key('CDDB_PATH'):
60 path = os.environ['CDDB_PATH']
Sjoerd Mullenderc9d73d11993-09-27 12:36:01 +000061 cddb_path = string.splitfields(path, ',')
62 else:
Sjoerd Mullendere202c381994-09-06 16:19:03 +000063 home = os.environ['HOME']
Sjoerd Mullenderc9d73d11993-09-27 12:36:01 +000064 cddb_path = [home + '/' + _cddbrc]
Sjoerd Mullendere202c381994-09-06 16:19:03 +000065
66 self._get_id(tracklist)
67
68 for dir in cddb_path:
69 file = dir + '/' + self.id + '.rdb'
70 try:
71 f = open(file, 'r')
72 self.file = file
73 break
74 except IOError:
75 pass
76 ntracks = string.atoi(self.id[:2], 16)
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +000077 self.artist = ''
78 self.title = ''
Sjoerd Mullendere202c381994-09-06 16:19:03 +000079 self.track = [None] + [''] * ntracks
80 if not hasattr(self, 'file'):
81 return
82 import regex
83 reg = regex.compile('^\\([^.]*\\)\\.\\([^:]*\\):\t\\(.*\\)')
84 while 1:
85 line = f.readline()
86 if not line:
87 break
88 if reg.match(line) == -1:
89 print 'syntax error in ' + file
90 continue
91 name1 = line[reg.regs[1][0]:reg.regs[1][1]]
92 name2 = line[reg.regs[2][0]:reg.regs[2][1]]
93 value = line[reg.regs[3][0]:reg.regs[3][1]]
94 if name1 == 'album':
95 if name2 == 'artist':
96 self.artist = value
97 elif name2 == 'title':
98 self.title = value
99 elif name2 == 'toc':
100 if not self.toc:
101 self.toc = value
102 if self.toc != value:
103 print 'toc\'s don\'t match'
104 elif name1[:5] == 'track':
105 try:
106 trackno = string.atoi(name1[5:])
107 except strings.atoi_error:
108 print 'syntax error in ' + file
109 continue
110 if trackno > ntracks:
111 print 'track number ' + `trackno` + \
112 ' in file ' + file + \
113 ' out of range'
114 continue
115 self.track[trackno] = value
116 f.close()
117 for i in range(2, len(self.track)):
118 track = self.track[i]
119 # if track title starts with `,', use initial part
120 # of previous track's title
121 if track and track[0] == ',':
122 try:
123 off = string.index(self.track[i - 1],
124 ',')
125 except string.index_error:
126 pass
127 else:
128 self.track[i] = self.track[i-1][:off] \
129 + track
130
131 def _get_id(self, tracklist):
132 # fill in self.id and self.toc.
133 # if the argument is a string ending in .rdb, the part
134 # upto the suffix is taken as the id.
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000135 if type(tracklist) == type(''):
Sjoerd Mullendere202c381994-09-06 16:19:03 +0000136 if tracklist[-4:] == '.rdb':
137 self.id = tracklist[:-4]
138 self.toc = ''
139 return
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000140 t = []
141 for i in range(2, len(tracklist), 4):
142 t.append((None, \
143 (string.atoi(tracklist[i:i+2]), \
144 string.atoi(tracklist[i+2:i+4]))))
145 tracklist = t
146 ntracks = len(tracklist)
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000147 self.id = _dbid((ntracks >> 4) & 0xF) + _dbid(ntracks & 0xF)
148 if ntracks <= _DB_ID_NTRACKS:
149 nidtracks = ntracks
150 else:
151 nidtracks = _DB_ID_NTRACKS - 1
152 min = 0
153 sec = 0
154 for track in tracklist:
155 start, length = track
156 min = min + length[0]
157 sec = sec + length[1]
158 min = min + sec / 60
159 sec = sec % 60
160 self.id = self.id + _dbid(min) + _dbid(sec)
161 for i in range(nidtracks):
162 start, length = tracklist[i]
163 self.id = self.id + _dbid(length[0]) + _dbid(length[1])
164 self.toc = string.zfill(ntracks, 2)
165 for track in tracklist:
166 start, length = track
167 self.toc = self.toc + string.zfill(length[0], 2) + \
168 string.zfill(length[1], 2)
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000169
170 def write(self):
Sjoerd Mullenderb2e358d1993-11-08 15:10:43 +0000171 import posixpath
Sjoerd Mullendere202c381994-09-06 16:19:03 +0000172 if os.environ.has_key('CDDB_WRITE_DIR'):
173 dir = os.environ['CDDB_WRITE_DIR']
Sjoerd Mullenderc9d73d11993-09-27 12:36:01 +0000174 else:
Sjoerd Mullendere202c381994-09-06 16:19:03 +0000175 dir = os.environ['HOME'] + '/' + _cddbrc
Sjoerd Mullenderc9d73d11993-09-27 12:36:01 +0000176 file = dir + '/' + self.id + '.rdb'
Sjoerd Mullenderb2e358d1993-11-08 15:10:43 +0000177 if posixpath.exists(file):
178 # make backup copy
179 posix.rename(file, file + '~')
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000180 f = open(file, 'w')
181 f.write('album.title:\t' + self.title + '\n')
182 f.write('album.artist:\t' + self.artist + '\n')
183 f.write('album.toc:\t' + self.toc + '\n')
Guido van Rossumb6775db1994-08-01 11:34:53 +0000184 prevpref = None
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000185 for i in range(1, len(self.track)):
Guido van Rossumb6775db1994-08-01 11:34:53 +0000186 track = self.track[i]
187 try:
188 off = string.index(track, ',')
189 except string.index_error:
190 prevpref = None
191 else:
192 if prevpref and track[:off] == prevpref:
193 track = track[off:]
194 else:
195 prevpref = track[:off]
196 f.write('track' + `i` + '.title:\t' + track + '\n')
Sjoerd Mullender4fff13f1992-12-14 13:16:55 +0000197 f.close()