-
Notifications
You must be signed in to change notification settings - Fork 0
/
cuesheet.py
109 lines (91 loc) · 2.48 KB
/
cuesheet.py
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
import re
cdtext_re = {
'REM': r'^(REM) (.+)$',
'PERFORMER': r'^(PERFORMER) "?(.+?)"?$',
'TITLE': r'^(TITLE) "?(.+?)"?$',
'FILE': r'^(FILE) "?(.+?)"? (BINARY|MOTOROLA|AIFF|WAVE|MP3)$',
'TRACK': r'^(TRACK) (\d+) (AUDIO|CDG|MODE1/2048|MODE1/2352|MODE2/2336|MODE2/2352|CDI/2336|CDI2352)$',
'INDEX': r'^(INDEX) (\d+) (\d+):(\d+):(\d+)$',
'FLAGS': r'^((?:DCP|4CH|PRE|SCMS) ?){1,4}$',
'ISRC': r'^(ISRC) (\w{5}\d{7})$',
'SONGWRITER': r'^(SONGWRITER) "?(.+?)"?$',
'CATALOG': r'^(CATALOG) (\d{13})$',
}
for k, v in cdtext_re.iteritems():
cdtext_re[k] = re.compile(v)
class CDText(object):
def __init__(self, str):
name = str.split()[0]
self.re = cdtext_re[name]
l = self.parse(str)
self.type, self.value = l[0], l[1:]
if type(self.value) == tuple and len(self.value) == 1:
self.value = self.value[0]
def __repr__(self):
return '<CDText "%s" "%s">' % (self.type, self.value)
def __str__(self):
return repr(self)
def parse(self, str):
r = self.re.match(str)
if not r:
return None, None
return r.groups()
class FieldDescriptor(object):
def __init__(self, field):
self.field = field
def __get__(self, instance, owner):
def find(name):
for l in instance.cdtext:
if l.type == name:
return l
cdtext = find(self.field)
return cdtext.value if cdtext else None
class Track(object):
def __init__(self):
self.cdtext = []
self.abs_tot, self.abs_end, self.nextstart = 0, 0, None
def add(self, cdtext):
self.cdtext.append(cdtext)
def set_abs_tot(self, tot):
self.abs_tot = tot
def set_abs_end(self, end):
self.abs_end
def get_start_time(self):
index = self.index
return int(index[1])*60 + int(index[2]) + float(index[3])/75
def get_length(self):
return self.nextstart - self.get_start_time()
for f in cdtext_re.keys():
setattr(Track, f.lower(), FieldDescriptor(f))
class Cuesheet(object):
def __init__(self, filename = None, fileobj = None):
if not fileobj and filename:
fileobj = open(filename, 'rb')
if fileobj:
self.parse(fileobj)
def parse(self, f):
info = []
tracks = []
track = Track()
info.append(track)
if not f.read(3) == '\xef\xbb\xbf':
f.seek(0)
for line in f:
line = line.strip()
if not len(line):
continue
cdtext = CDText(line)
if cdtext.type == 'TRACK':
track = Track()
tracks.append(track)
track.add(cdtext)
self.info = info
self.tracks = tracks
def get_next(self, track):
found = False
for i in self.tracks:
if found:
return i
elif i == track:
found = True
return None