13 def open(self
, name
, mode
):
14 self
.fd
= posix
.open(name
, mode
)
18 return posix
.read(self
.fd
, len)
20 def write(self
, data
):
21 dummy
= posix
.write(self
.fd
, data
)
30 dummy
= posix
.close(self
.fd
)
32 def packttyargs(*args
):
33 if type(args
) <> type(()):
34 raise 'Incorrect argtype for packttyargs'
35 if type(args
[0]) == type(1):
36 iflag
, oflag
, cflag
, lflag
, line
, chars
= args
37 elif type(args
[0]) == type(()):
39 raise 'Only 1 argument expected'
40 iflag
, oflag
, cflag
, lflag
, line
, chars
= args
[0]
41 elif type(args
[0]) == type([]):
43 raise 'Only 1 argument expected'
44 [iflag
, oflag
, cflag
, lflag
, line
, chars
] = args
[0]
45 str = struct
.pack('hhhhb', iflag
, oflag
, cflag
, lflag
, line
)
51 chars
= ['\0']*IOCTL
.NCCS
52 return packttyargs(0, 0, 0, 0, 0, chars
)
54 def unpackttyargs(str):
55 args
= str[:-IOCTL
.NCCS
]
56 rawchars
= str[-IOCTL
.NCCS
:]
60 iflag
, oflag
, cflag
, lflag
, line
= struct
.unpack('hhhhb', args
)
61 return (iflag
, oflag
, cflag
, lflag
, line
, chars
)
64 fp
= UnixFile().open(name
, 2)
67 rv
= fcntl
.ioctl(fd
, IOCTL
.TCGETA
, nullttyargs())
68 iflag
, oflag
, cflag
, lflag
, line
, chars
= unpackttyargs(rv
)
69 iflag
= iflag
& ~
(INPCK|ISTRIP|INLCR|IUCLC|IXON|IXOFF
)
70 oflag
= oflag
& ~OPOST
71 cflag
= B9600|CS8|CREAD|CLOCAL
72 lflag
= lflag
& ~
(ISIG|ICANON|ECHO|TOSTOP
)
75 arg
= packttyargs(iflag
, oflag
, cflag
, lflag
, line
, chars
)
76 dummy
= fcntl
.ioctl(fd
, IOCTL
.TCSETA
, arg
)
95 CTRL_ENABLE
= EXP_8
+ '\xc6'
96 SEARCH_DATA
= EXP_8
+ '\x93'
105 STEP_FWD
='\x2b' # Was: '\xad'
106 FM_SELECT
=EXP_8
+ '\xc8'
107 FM_STILL
=EXP_8
+ '\xcd'
108 PREVIEW
=EXP_7
+ '\x9d'
109 REVIEW
=EXP_7
+ '\x9e'
110 DM_OFF
=EXP_8
+ '\xc9'
111 DM_SET
=EXP_8
+ '\xc4'
114 EM_SELECT
=EXP_8
+ '\xc0'
115 N_FRAME_REC
=EXP_8
+ '\x92'
116 SEARCH_PREROLL
=EXP_8
+ '\x90'
117 EDIT_PB_STANDBY
=EXP_8
+ '\x96'
118 EDIT_PLAY
=EXP_8
+ '\x98'
119 AUTO_EDIT
=EXP_7
+ '\x9c'
121 IN_ENTRY
=EXP_7
+ '\x90'
122 IN_ENTRY_RESET
=EXP_7
+ '\x91'
123 IN_ENTRY_SET
=EXP_7
+ '\x98'
124 IN_ENTRY_INC
=EXP_7
+ '\x94'
125 IN_ENTRY_DEC
=EXP_7
+ '\x95'
126 IN_ENTRY_SENSE
=EXP_7
+ '\x9a'
128 OUT_ENTRY
=EXP_7
+ '\x92'
129 OUT_ENTRY_RESET
=EXP_7
+ '\x93'
130 OUT_ENTRY_SET
=EXP_7
+ '\x99'
131 OUT_ENTRY_INC
=EXP_7
+ '\x96'
132 OUT_ENTRY_DEC
=EXP_7
+ '\x98'
133 OUT_ENTRY_SENSE
=EXP_7
+ '\x9b'
136 MUTE_AUDIO_OFF
= '\x25'
138 MUTE_VIDEO_OFF
= '\x27'
139 MUTE_AV
= EXP_7
+ '\xc6'
140 MUTE_AV_OFF
= EXP_7
+ '\xc7'
146 self
.ifp
, self
.ofp
= initline(DEVICE
)
154 raise error
, 'Another command active: '+self
.busy_cmd
156 def _endlongcmd(self
, name
):
164 return self
.ifp
.fileno()
166 def setasync(self
, async):
169 def setcallback(self
, cb
, arg
):
176 raise error
, 'Can only call poll() in async mode'
177 if not self
.busy_cmd
:
181 apply(self
.cb
, (self
.cb_arg
,))
189 def _waitdata(self
, len, tout
):
193 ready
, d1
, d2
= select
.select( \
196 ready
, d1
, d2
= select
.select( \
197 [self
.ifp
], [], [], tout
)
200 ## print 'FLUSHED:', `rep`
202 data
= self
.ifp
.read(1)
211 def _reply(self
, len):
212 data
= self
._waitdata
(len, 10)
214 raise error
, 'Lost contact with VCR'
217 def _getnumber(self
, len):
218 data
= self
._reply
(len)
221 digit
= ord(c
) - NUMBER_N
222 if digit
< 0 or digit
> 9:
223 raise error
, 'Non-digit in number'+`c`
224 number
= number
*10 + digit
228 dummy
= self
._waitdata
(10000, 0)
230 ## print 'IFLUSH:', dummy
232 def simplecmd(self
,cmd
):
240 raise error
, 'Unexpected reply:' + `rep`
243 def replycmd(self
, cmd
):
244 if not self
.simplecmd(cmd
[:-1]):
248 def _number(self
, number
, digits
):
250 raise error
, 'Unexpected negative number:'+ `number`
251 maxnum
= pow(10, digits
)
253 raise error
, 'Number too big'
255 number
= number
% maxnum
257 digit
= number
/ maxnum
258 ok
= self
.simplecmd(chr(NUMBER_N
+ digit
))
260 raise error
, 'Error while transmitting number'
262 def initvcr(self
, *optarg
):
266 starttime
= time
.time()
272 rep
= self
._waitdata
(1, 2)
274 if rep
in ( None, CL
, NAK
):
276 if time
.time() - starttime
> timeout
:
282 raise error
, 'Unexpected reply:' + `rep`
283 dummy
= self
.simplecmd(CTRL_ENABLE
)
286 rep
= self
._waitdata
(1, None)
288 raise error
, 'Unexpected None reply from waitdata'
289 if rep
not in (COMPLETION
, ACK
):
291 raise error
, 'Unexpected waitready reply:' + `rep`
295 rep
= self
._waitdata
(1, 0)
298 if rep
not in (COMPLETION
, ACK
):
300 raise error
, 'Unexpected waitready reply:' + `rep`
304 def play(self
): return self
.simplecmd(PLAY
)
305 def stop(self
): return self
.simplecmd(STOP
)
306 def ff(self
): return self
.simplecmd(FF
)
307 def rew(self
): return self
.simplecmd(REW
)
308 def eject(self
):return self
.simplecmd(EJECT
)
309 def still(self
):return self
.simplecmd(STILL
)
310 def step(self
): return self
.simplecmd(STEP_FWD
)
312 def goto(self
, (h
, m
, s
, f
)):
313 if not self
.simplecmd(SEARCH_DATA
):
319 if not self
.simplecmd(ENTER
):
321 return self
._endlongcmd
('goto')
323 # XXXX TC_SENSE doesn't seem to work
324 def faulty_where(self
):
327 h
= self
._getnumber
(2)
328 m
= self
._getnumber
(2)
329 s
= self
._getnumber
(2)
330 f
= self
._getnumber
(2)
334 return self
.addr2tc(self
.sense())
338 self
._cmd
(ADDR_SENSE
)
339 num
= self
._getnumber
(5)
342 def addr2tc(self
, num
):
351 def tc2addr(self
, (h
, m
, s
, f
)):
352 return ((h
*60 + m
)*60 + s
)*25 + f
354 def fmmode(self
, mode
):
358 elif mode
== 'buffer':
363 raise error
, 'fmmode arg should be off, buffer or dnr'
364 if not self
.simplecmd(FM_SELECT
):
367 if not self
.simplecmd(ENTER
):
371 def mute(self
, mode
, value
):
374 cmds
= (MUTE_AUDIO_OFF
, MUTE_AUDIO
)
375 elif mode
== 'video':
376 cmds
= (MUTE_VIDEO_OFF
, MUTE_VIDEO
)
378 cmds
= (MUTE_AV_OFF
, MUTE_AV
)
380 raise error
, 'mute type should be audio, video or av'
382 return self
.simplecmd(cmd
)
384 def editmode(self
, mode
):
388 elif mode
== 'format':
392 elif mode
== 'asmbl':
396 elif mode
== 'insert-video':
401 raise 'editmode should be off,format,asmbl or insert-video'
402 if not self
.simplecmd(EM_SELECT
):
407 if not self
.simplecmd(ENTER
):
413 return self
._endlongcmd
(AUTO_EDIT
)
415 def nframerec(self
, num
):
416 if not self
.simplecmd(N_FRAME_REC
):
419 if not self
.simplecmd(ENTER
):
421 return self
._endlongcmd
('nframerec')
424 if not self
.simplecmd(FM_STILL
):
426 return self
._endlongcmd
('fmstill')
429 if not self
.simplecmd(PREVIEW
):
431 return self
._endlongcmd
('preview')
434 if not self
.simplecmd(REVIEW
):
436 return self
._endlongcmd
('review')
438 def search_preroll(self
):
439 if not self
.simplecmd(SEARCH_PREROLL
):
441 return self
._endlongcmd
('search_preroll')
443 def edit_pb_standby(self
):
444 if not self
.simplecmd(EDIT_PB_STANDBY
):
446 return self
._endlongcmd
('edit_pb_standby')
449 if not self
.simplecmd(EDIT_PLAY
):
451 return self
._endlongcmd
('edit_play')
453 def dmcontrol(self
, mode
):
456 return self
.simplecmd(DM_OFF
)
457 if mode
== 'multi freeze':
459 elif mode
== 'zoom freeze':
461 elif mode
== 'digital slow':
463 elif mode
== 'freeze':
466 raise error
, 'unknown dmcontrol argument: ' + `mode`
467 if not self
.simplecmd(DM_SET
):
470 if not self
.simplecmd(ENTER
):
474 def fwdshuttle(self
, num
):
475 if not self
.simplecmd(FWD_SHUTTLE
):
480 def revshuttle(self
, num
):
481 if not self
.simplecmd(REV_SHUTTLE
):
486 def getentry(self
, which
):
491 cmd
= OUT_ENTRY_SENSE
493 h
= self
._getnumber
(2)
494 m
= self
._getnumber
(2)
495 s
= self
._getnumber
(2)
496 f
= self
._getnumber
(2)
499 def inentry(self
, arg
):
500 return self
.ioentry(arg
, (IN_ENTRY
, IN_ENTRY_RESET
, \
501 IN_ENTRY_SET
, IN_ENTRY_INC
, IN_ENTRY_DEC
))
503 def outentry(self
, arg
):
504 return self
.ioentry(arg
, (OUT_ENTRY
, OUT_ENTRY_RESET
, \
505 OUT_ENTRY_SET
, OUT_ENTRY_INC
, OUT_ENTRY_DEC
))
507 def ioentry(self
, arg
, (Load
, Clear
, Set
, Inc
, Dec
)):
509 if type(arg
) == type(()):
511 if not self
.simplecmd(Set
):
517 if not self
.simplecmd(ENTER
):
529 raise error
, 'Arg should be +,-,reset,load or (h,m,s,f)'
530 return self
.simplecmd(cmd
)
533 d
= self
.simplecmd(CL
)