diff options
Diffstat (limited to 'Demo/sgi/video/VCR.py')
-rwxr-xr-x | Demo/sgi/video/VCR.py | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/Demo/sgi/video/VCR.py b/Demo/sgi/video/VCR.py new file mode 100755 index 0000000..dda2601 --- /dev/null +++ b/Demo/sgi/video/VCR.py @@ -0,0 +1,297 @@ +import fcntl +import IOCTL +from IOCTL import * +import sys +import struct +import select + +DEVICE='/dev/ttyd2' + +def packttyargs(*args): + if type(args) <> type(()): + raise 'Incorrect argtype for packttyargs' + if type(args[0]) == type(1): + iflag, oflag, cflag, lflag, line, chars = args + elif type(args[0]) == type(()): + if len(args) <> 1: + raise 'Only 1 argument expected' + iflag, oflag, cflag, lflag, line, chars = args[0] + elif type(args[0]) == type([]): + if len(args) <> 1: + raise 'Only 1 argument expected' + [iflag, oflag, cflag, lflag, line, chars] = args[0] + str = struct.pack('hhhhb', iflag, oflag, cflag, lflag, line) + for c in chars: + str = str + c + return str + +def nullttyargs(): + chars = ['\0']*IOCTL.NCCS + return packttyargs(0, 0, 0, 0, 0, chars) + +def unpackttyargs(str): + args = str[:-IOCTL.NCCS] + rawchars = str[-IOCTL.NCCS:] + chars = [] + for c in rawchars: + chars.append(c) + iflag, oflag, cflag, lflag, line = struct.unpack('hhhhb', args) + return (iflag, oflag, cflag, lflag, line, chars) + +def initline(name): + fp = open(name, 'r') + ofp = open(name, 'w') + fd = fp.fileno() + rv = fcntl.ioctl(fd, IOCTL.TCGETA, nullttyargs()) + iflag, oflag, cflag, lflag, line, chars = unpackttyargs(rv) + iflag = iflag & ~(INPCK|ISTRIP|INLCR|IUCLC|IXON|IXOFF) + oflag = oflag & ~OPOST + cflag = B9600|CS8|CREAD|CLOCAL + lflag = lflag & ~(ISIG|ICANON|ECHO|TOSTOP) + chars[VMIN] = chr(1) + chars[VTIME] = chr(0) + arg = packttyargs(iflag, oflag, cflag, lflag, line, chars) + dummy = fcntl.ioctl(fd, IOCTL.TCSETA, arg) + return fp, ofp + +#ifp, ofp = initline('/dev/ttyd2') +#while 1: +# print 'GO' +# inset, d, d = select.select([sys.stdin, ifp], [], []) +# if sys.stdin in inset: +# cmd = eval(sys.stdin.readline(100)) +# print 'CMD:', `cmd` +# if cmd: +# ofp.write(cmd) +# ofp.flush() +# if ifp in inset: +# data = ifp.read(1) +# print 'LEN', len(data), 'DATA', `data` + +error = 'VCR.error' + +# Commands/replies: +COMPLETION = '\x01' +ACK ='\x0a' +NAK ='\x0b' + +NUMBER_N = 0x30 +ENTER = '\x40' + +EXP_7= '\xde' +EXP_8= '\xdf' + +CL ='\x56' +CTRL_ENABLE = EXP_8 + '\xc6' +SEARCH_DATA = EXP_8 + '\x93' +ADDR_SENSE = '\x60' + +PLAY ='\x3a' +STOP ='\x3f' +EJECT='\x2a' +FF ='\xab' +REW ='\xac' +STILL='\x4f' +STEP_FWD ='\xad' +FM_SELECT=EXP_8 + '\xc8' +FM_STILL=EXP_8 + '\xcd' +DM_OFF=EXP_8 + '\xc9' +DM_SET=EXP_8 + '\xc4' +FWD_SHUTTLE='\xb5' +REV_SHUTTLE='\xb6' + +class VCR(): + def init(self): + self.ifp, self.ofp = initline(DEVICE) + return self + + def _cmd(self, cmd): +## print '>>>',`cmd` + self.ofp.write(cmd) + self.ofp.flush() + + def _waitdata(self, len, tout): + rep = '' + while len > 0: + ready, d1, d2 = select.select([self.ifp], [], [], tout) + if ready == []: +## if rep: +## print 'FLUSHED:', `rep` + return None + data = self.ifp.read(1) +## print '<<<',`data` + if data == NAK: + return NAK + rep = rep + data + len = len - 1 + return rep + + def _reply(self, len): + data = self._waitdata(len, 10) + if data == None: + raise error, 'Lost contact with VCR' + return data + + def _getnumber(self, len): + data = self._reply(len) + number = 0 + for c in data: + digit = ord(c) - NUMBER_N + if digit < 0 or digit > 9: + raise error, 'Non-digit in number'+`c` + number = number*10 + digit + return number + + def _iflush(self): + dummy = self._waitdata(10000, 1) +## if dummy: +## print 'IFLUSH:', dummy + + def simplecmd(self,cmd): + for ch in cmd: + self._cmd(ch) + rep = self._reply(1) + if rep == NAK: + return 0 + elif rep <> ACK: + raise error, 'Unexpected reply:' + `rep` + return 1 + + def _number(self, number, digits): + if number < 0: + raise error, 'Unexpected negative number:'+ `number` + maxnum = pow(10, digits) + if number > maxnum: + raise error, 'Number too big' + while maxnum > 1: + number = number % maxnum + maxnum = maxnum / 10 + digit = number / maxnum + ok = self.simplecmd(chr(NUMBER_N + digit)) + if not ok: + raise error, 'Error while transmitting number' + + def wait(self): + self._iflush() + while 1: +## print 'SENDCL' + self._cmd(CL) + rep = self._waitdata(1, 2) +## print `rep` + if rep in ( None, CL, NAK ): + continue + break + if rep <> ACK: + raise error, 'Unexpected reply:' + `rep` + dummy = self.simplecmd(CTRL_ENABLE) + + def waitready(self): + rep = self._waitdata(1, 60) + if rep == None: + raise error, 'Command not finished in one minute' + if rep not in (COMPLETION, ACK): + self._iflush() + raise error, 'Unexpected waitready reply:' + `rep` + + def play(self): return self.simplecmd(PLAY) + def stop(self): return self.simplecmd(STOP) + def ff(self): return self.simplecmd(FF) + def rew(self): return self.simplecmd(REW) + def eject(self):return self.simplecmd(EJECT) + def still(self):return self.simplecmd(STILL) + def step(self): return self.simplecmd(STEP_FWD) + + def goto(self, (h, m, s, f)): + if not self.simplecmd(SEARCH_DATA): + return 0 + self._number(h, 2) + self._number(m, 2) + self._number(s, 2) + self._number(f, 2) + if not self.simplecmd(ENTER): + return 0 + self.waitready() + return 1 + + # XXXX TC_SENSE doesn't seem to work + def faulty_where(self): + self._cmd(TC_SENSE) + h = self._getnumber(2) + m = self._getnumber(2) + s = self._getnumber(2) + f = self._getnumber(2) + return (h, m, s, f) + + def where(self): + return self.addr2tc(self.sense()) + + def sense(self): + self._cmd(ADDR_SENSE) + num = self._getnumber(5) + return num + + def addr2tc(self, num): + f = num % 25 + num = num / 25 + s = num % 60 + num = num / 60 + m = num % 60 + h = num / 60 + return (h, m, s, f) + + def tc2addr(self, (h, m, s, f)): + return ((h*60 + m)*60 + s)*25 + f + + def fmmode(self, mode): + if mode == 'off': + arg = 0 + elif mode == 'buffer': + arg = 1 + elif mode == 'dnr': + arg = 2 + else: + raise error, 'fmmode arg should be off, buffer or dnr' + if not self.simplecmd(FM_SELECT): + return 0 + self._number(arg, 1) + if not self.simplecmd(ENTER): + return 0 + return 1 + + def fmstill(self): + if not self.simplecmd(FM_STILL): + return 0 + self.waitready() + return 1 + + def dmcontrol(self, mode): + if mode == 'off': + return self.simplecmd(DM_OFF) + if mode == 'multi freeze': + num = 1000 + elif mode == 'zoom freeze': + num = 2000 + elif mode == 'digital slow': + num = 3000 + elif mode == 'freeze': + num = 4011 + else: + raise error, 'unknown dmcontrol argument: ' + `mode` + if not self.simplecmd(DM_SET): + return 0 + self._number(num, 4) + if not self.simplecmd(ENTER): + return 0 + return 1 + + def fwdshuttle(self, num): + if not self.simplecmd(FWD_SHUTTLE): + return 0 + self._number(num, 1) + return 1 + + def revshuttle(self, num): + if not self.simplecmd(REV_SHUTTLE): + return 0 + self._number(num, 1) + return 1 |