# Class interface to the CD module.

import cd, CD

class Error(Exception):
	pass
class _Stop(Exception):
	pass

def _doatime(self, cb_type, data):
	if ((data[0] * 60) + data[1]) * 75 + data[2] > self.end:
##		print 'done with list entry', repr(self.listindex)
		raise _Stop
	func, arg = self.callbacks[cb_type]
	if func:
		func(arg, cb_type, data)

def _dopnum(self, cb_type, data):
	if data > self.end:
##		print 'done with list entry', repr(self.listindex)
		raise _Stop
	func, arg = self.callbacks[cb_type]
	if func:
		func(arg, cb_type, data)

class Readcd:
	def __init__(self, *arg):
		if len(arg) == 0:
			self.player = cd.open()
		elif len(arg) == 1:
			self.player = cd.open(arg[0])
		elif len(arg) == 2:
			self.player = cd.open(arg[0], arg[1])
		else:
			raise Error, 'bad __init__ call'
		self.list = []
		self.callbacks = [(None, None)] * 8
		self.parser = cd.createparser()
		self.playing = 0
		self.end = 0
		self.status = None
		self.trackinfo = None

	def eject(self):
		self.player.eject()
		self.list = []
		self.end = 0
		self.listindex = 0
		self.status = None
		self.trackinfo = None
		if self.playing:
##			print 'stop playing from eject'
			raise _Stop

	def pmsf2msf(self, track, min, sec, frame):
		if not self.status:
			self.cachestatus()
		if track < self.status[5] or track > self.status[6]:
			raise Error, 'track number out of range'
		if not self.trackinfo:
			self.cacheinfo()
		start, total = self.trackinfo[track]
		start = ((start[0] * 60) + start[1]) * 75 + start[2]
		total = ((total[0] * 60) + total[1]) * 75 + total[2]
		block = ((min * 60) + sec) * 75 + frame
		if block > total:
			raise Error, 'out of range'
		block = start + block
		min, block = divmod(block, 75*60)
		sec, frame = divmod(block, 75)
		return min, sec, frame

	def reset(self):
		self.list = []

	def appendtrack(self, track):
		self.appendstretch(track, track)
				
	def appendstretch(self, start, end):
		if not self.status:
			self.cachestatus()
		if not start:
			start = 1
		if not end:
			end = self.status[6]
		if type(end) == type(0):
			if end < self.status[5] or end > self.status[6]:
				raise Error, 'range error'
		else:
			l = len(end)
			if l == 4:
				prog, min, sec, frame = end
				if prog < self.status[5] or prog > self.status[6]:
					raise Error, 'range error'
				end = self.pmsf2msf(prog, min, sec, frame)
			elif l != 3:
				raise Error, 'syntax error'
		if type(start) == type(0):
			if start < self.status[5] or start > self.status[6]:
				raise Error, 'range error'
			if len(self.list) > 0:
				s, e = self.list[-1]
				if type(e) == type(0):
					if start == e+1:
						start = s
						del self.list[-1]
		else:
			l = len(start)
			if l == 4:
				prog, min, sec, frame = start
				if prog < self.status[5] or prog > self.status[6]:
					raise Error, 'range error'
				start = self.pmsf2msf(prog, min, sec, frame)
			elif l != 3:
				raise Error, 'syntax error'
		self.list.append((start, end))

	def settracks(self, list):
		self.list = []
		for track in list:
			self.appendtrack(track)

	def setcallback(self, cb_type, func, arg):
		if cb_type < 0 or cb_type >= 8:
			raise Error, 'type out of range'
		self.callbacks[cb_type] = (func, arg)
		if self.playing:
			start, end = self.list[self.listindex]
			if type(end) == type(0):
				if cb_type != CD.PNUM:
					self.parser.setcallback(cb_type, func, arg)
			else:
				if cb_type != CD.ATIME:
					self.parser.setcallback(cb_type, func, arg)

	def removecallback(self, cb_type):
		if cb_type < 0 or cb_type >= 8:
			raise Error, 'type out of range'
		self.callbacks[cb_type] = (None, None)
		if self.playing:
			start, end = self.list[self.listindex]
			if type(end) == type(0):
				if cb_type != CD.PNUM:
					self.parser.removecallback(cb_type)
			else:
				if cb_type != CD.ATIME:
					self.parser.removecallback(cb_type)

	def gettrackinfo(self, *arg):
		if not self.status:
			self.cachestatus()
		if not self.trackinfo:
			self.cacheinfo()
		if len(arg) == 0:
			return self.trackinfo[self.status[5]:self.status[6]+1]
		result = []
		for i in arg:
			if i < self.status[5] or i > self.status[6]:
				raise Error, 'range error'
			result.append(self.trackinfo[i])
		return result

	def cacheinfo(self):
		if not self.status:
			self.cachestatus()
		self.trackinfo = []
		for i in range(self.status[5]):
			self.trackinfo.append(None)
		for i in range(self.status[5], self.status[6]+1):
			self.trackinfo.append(self.player.gettrackinfo(i))

	def cachestatus(self):
		self.status = self.player.getstatus()
		if self.status[0] == CD.NODISC:
			self.status = None
			raise Error, 'no disc in player'

	def getstatus(self):
		return self.player.getstatus()

	def play(self):
		if not self.status:
			self.cachestatus()
		size = self.player.bestreadsize()
		self.listindex = 0
		self.playing = 0
		for i in range(8):
			func, arg = self.callbacks[i]
			if func:
				self.parser.setcallback(i, func, arg)
			else:
				self.parser.removecallback(i)
		if len(self.list) == 0:
			for i in range(self.status[5], self.status[6]+1):
				self.appendtrack(i)
		try:
			while 1:
				if not self.playing:
					if self.listindex >= len(self.list):
						return
					start, end = self.list[self.listindex]
					if type(start) == type(0):
						dummy = self.player.seektrack(
							start)
					else:
						min, sec, frame = start
						dummy = self.player.seek(
							min, sec, frame)
					if type(end) == type(0):
						self.parser.setcallback(
							CD.PNUM, _dopnum, self)
						self.end = end
						func, arg = \
						      self.callbacks[CD.ATIME]
						if func:
							self.parser.setcallback(CD.ATIME, func, arg)
						else:
							self.parser.removecallback(CD.ATIME)
					else:
						min, sec, frame = end
						self.parser.setcallback(
							CD.ATIME, _doatime,
							self)
						self.end = (min * 60 + sec) * \
							   75 + frame
						func, arg = \
						      self.callbacks[CD.PNUM]
						if func:
							self.parser.setcallback(CD.PNUM, func, arg)
						else:
							self.parser.removecallback(CD.PNUM)
					self.playing = 1
				data = self.player.readda(size)
				if data == '':
					self.playing = 0
					self.listindex = self.listindex + 1
					continue
				try:
					self.parser.parseframe(data)
				except _Stop:
					self.playing = 0
					self.listindex = self.listindex + 1
		finally:
			self.playing = 0
