Commit b2dae969 authored by Guido van Rossum's avatar Guido van Rossum

Created Vedit.py, the video editor. This uses the classes in Viewer.py.

Viewer.py in turn requires changes to VFile.py (unfortunately that file
is now a complete mess...).
parent 4dfc2032
......@@ -100,6 +100,10 @@ Vtime.py (unrelated to vtime!!!) Copy a video file,
manipulating the time codes (e.g. faster/slower, or
regenerate time codes, or drop frames too close apart)
Vedit.py interactive video editing program
Viewer.py two viewer classes used by Vedit
The following are C programs, either for efficiency or because they
need to link with a C library:
......
......@@ -52,7 +52,138 @@ def conv_rgb8(rgb,d1,d2):
# xorigin, yorigin
# fallback
class VinFile:
# XXX it's a total mess now -- VFile is a new base class
# XXX to support common functionality (e.g. showframe)
class VFile:
#
# getinfo returns all info pertaining to a film. The returned tuple
# can be passed to VoutFile.setinfo()
#
def getinfo(self):
return (self.format, self.width, self.height, self.packfactor,\
self.c0bits, self.c1bits, self.c2bits, self.offset, \
self.chrompack)
# reopen() raises Error if the header is bad (which can only
# happen if the file was written to since opened).
def reopen(self):
self.fp.seek(0)
x = self.initfp(self.fp, self.filename)
def setconvcolor(self):
try:
self.convcolor = eval('conv_'+self.format)
except:
raise Error, \
self.filename + ': unknown colorsys ' + self.format
def showframe(self, data, chromdata):
w, h, pf = self.width, self.height, self.packfactor
if not self.colormapinited:
self.initcolormap()
factor = self.magnify
if pf: factor = factor * pf
if chromdata and not self.skipchrom:
cp = self.chrompack
cw = (w+cp-1)/cp
ch = (h+cp-1)/cp
gl.rectzoom(factor*cp, factor*cp)
gl.pixmode(GL.PM_SIZE, 16)
gl.writemask(self.mask - ((1 << self.c0bits) - 1))
gl.lrectwrite(self.xorigin, self.yorigin, \
self.xorigin + cw - 1, self.yorigin + ch - 1, \
chromdata)
#
if pf:
gl.writemask((1 << self.c0bits) - 1)
gl.pixmode(GL.PM_SIZE, 8)
gl.rectzoom(factor, factor)
w = w/pf
h = h/pf
gl.lrectwrite(self.xorigin, self.yorigin, \
self.xorigin + w - 1, self.yorigin + h - 1, data)
def initcolormap(self):
self.colormapinited = 1
if self.format == 'rgb':
gl.RGBmode()
gl.gconfig()
gl.RGBcolor(200, 200, 200)
gl.clear()
return
gl.cmode()
gl.gconfig()
self.skipchrom = 0
if not self.quiet:
sys.stderr.write('Initializing color map...')
self.initcmap()
if not self.quiet:
sys.stderr.write(' Done.\n')
if self.offset == 0:
gl.color(0x800)
gl.clear()
self.mask = 0x7ff
else:
self.mask = 0xfff
gl.clear()
def initcmap(self):
maxbits = gl.getgdesc(GL.GD_BITS_NORM_SNG_CMODE)
if maxbits > 11:
maxbits = 11
c0bits, c1bits, c2bits = self.c0bits, self.c1bits, self.c2bits
if c0bits+c1bits+c2bits > maxbits:
if self.fallback and c0bits < maxbits:
# Cannot display film in this mode, use mono
self.skipchrom = 1
c1bits = c2bits = 0
self.convcolor = conv_grey
else:
raise Error, 'Sorry, '+`maxbits`+ \
' bits max on this machine'
maxc0 = 1 << c0bits
maxc1 = 1 << c1bits
maxc2 = 1 << c2bits
if self.offset == 0 and maxbits == 11:
offset = 2048
else:
offset = self.offset
if maxbits <> 11:
offset = offset & ((1<<maxbits)-1)
#for i in range(512, MAXMAP):
# gl.mapcolor(i, 0, 0, 0)
#void = gl.qtest() # Should be gl.gflush()
for c0 in range(maxc0):
c0v = c0/float(maxc0-1)
for c1 in range(maxc1):
if maxc1 == 1:
c1v = 0
else:
c1v = c1/float(maxc1-1)
for c2 in range(maxc2):
if maxc2 == 1:
c2v = 0
else:
c2v = c2/float(maxc2-1)
index = offset + c0 + (c1<<c0bits) + \
(c2 << (c0bits+c1bits))
rv, gv, bv = self.convcolor( \
c0v, c1v, c2v)
r, g, b = int(rv*255.0), \
int(gv*255.0), int(bv*255.0)
if index < MAXMAP:
gl.mapcolor(index, r, g, b)
void = gl.gflush()
class VinFile(VFile):
# init() and initfp() raise Error if the header is bad.
# init() raises whatever open() raises if the file can't be opened.
......@@ -122,11 +253,7 @@ class VinFile:
raise Error, \
self.filename + ': bad 3.0 color info'
try:
self.convcolor = eval('conv_'+self.format)
except:
raise Error, \
self.filename + ': unknown colorsys ' + self.format
self.setconvcolor()
#
line = self.fp.readline()
try:
......@@ -162,23 +289,6 @@ class VinFile:
self.fp.close()
self.fp = None
#
# getinfo returns all info pertaining to a film. The returned tuple
# can be passed to VoutFile.setinfo()
#
def getinfo(self):
return (self.format, self.width, self.height, self.packfactor,\
self.c0bits, self.c1bits, self.c2bits, self.offset, \
self.chrompack)
# reopen() raises Error if the header is bad (which can only
# happen if the file was written to since opened).
def reopen(self):
self.fp.seek(0)
x = self.initfp(self.fp, self.filename)
def rewind(self):
if self.hascache:
self.frameno = 0
......@@ -270,105 +380,6 @@ class VinFile:
self.showframe(data, chromdata)
return time
def showframe(self, data, chromdata):
w, h, pf = self.width, self.height, self.packfactor
if not self.colormapinited:
self.initcolormap()
factor = self.magnify
if pf: factor = factor * pf
if chromdata and not self.skipchrom:
cp = self.chrompack
cw = (w+cp-1)/cp
ch = (h+cp-1)/cp
gl.rectzoom(factor*cp, factor*cp)
gl.pixmode(GL.PM_SIZE, 16)
gl.writemask(self.mask - ((1 << self.c0bits) - 1))
gl.lrectwrite(self.xorigin, self.yorigin, \
self.xorigin + cw - 1, self.yorigin + ch - 1, \
chromdata)
#
if pf:
gl.writemask((1 << self.c0bits) - 1)
gl.pixmode(GL.PM_SIZE, 8)
gl.rectzoom(factor, factor)
w = w/pf
h = h/pf
gl.lrectwrite(self.xorigin, self.yorigin, \
self.xorigin + w - 1, self.yorigin + h - 1, data)
def initcolormap(self):
self.colormapinited = 1
if self.format == 'rgb':
gl.RGBmode()
gl.gconfig()
gl.RGBcolor(200, 200, 200)
gl.clear()
return
gl.cmode()
gl.gconfig()
self.skipchrom = 0
if not self.quiet:
sys.stderr.write('Initializing color map...')
self.initcmap()
if not self.quiet:
sys.stderr.write(' Done.\n')
if self.offset == 0:
gl.color(0x800)
gl.clear()
self.mask = 0x7ff
else:
self.mask = 0xfff
gl.clear()
def initcmap(self):
maxbits = gl.getgdesc(GL.GD_BITS_NORM_SNG_CMODE)
if maxbits > 11:
maxbits = 11
c0bits, c1bits, c2bits = self.c0bits, self.c1bits, self.c2bits
if c0bits+c1bits+c2bits > maxbits:
if self.fallback and c0bits < maxbits:
# Cannot display film in this mode, use mono
self.skipchrom = 1
c1bits = c2bits = 0
self.convcolor = conv_grey
else:
raise Error, 'Sorry, '+`maxbits`+ \
' bits max on this machine'
maxc0 = 1 << c0bits
maxc1 = 1 << c1bits
maxc2 = 1 << c2bits
if self.offset == 0 and maxbits == 11:
offset = 2048
else:
offset = self.offset
if maxbits <> 11:
offset = offset & ((1<<maxbits)-1)
#for i in range(512, MAXMAP):
# gl.mapcolor(i, 0, 0, 0)
#void = gl.qtest() # Should be gl.gflush()
for c0 in range(maxc0):
c0v = c0/float(maxc0-1)
for c1 in range(maxc1):
if maxc1 == 1:
c1v = 0
else:
c1v = c1/float(maxc1-1)
for c2 in range(maxc2):
if maxc2 == 1:
c2v = 0
else:
c2v = c2/float(maxc2-1)
index = offset + c0 + (c1<<c0bits) + \
(c2 << (c0bits+c1bits))
rv, gv, bv = self.convcolor( \
c0v, c1v, c2v)
r, g, b = int(rv*255.0), \
int(gv*255.0), int(bv*255.0)
if index < MAXMAP:
gl.mapcolor(index, r, g, b)
void = gl.gflush()
#
# A set of routines to grab images from windows
#
......@@ -417,7 +428,7 @@ def grab_hsv(w, h, pf):
# Notably it will accept almost any garbage and write it to the video
# output file
#
class VoutFile:
class VoutFile(VFile):
def init(self, filename):
if filename == '-':
return self.initfp(sys.stdout, filename)
......@@ -434,21 +445,21 @@ class VoutFile:
self.offset = 0
self.chrompack = 0
self.headerwritten = 0
self.quiet = 0
self.magnify = 1
self.setconvcolor()
self.xorigin = self.yorigin = 0
return self
def close(self):
self.fp.close()
x = self.initfp(None, None)
def getinfo(self):
return (self.format, self.width, self.height, self.packfactor,\
self.c0bits, self.c1bits, self.c2bits, self.offset, \
self.chrompack)
def setinfo(self, values):
self.format, self.width, self.height, self.packfactor,\
self.c0bits, self.c1bits, self.c2bits, self.offset, \
self.chrompack = values
self.setconvcolor()
def writeheader(self):
self.headerwritten = 1
......
#! /ufs/guido/bin/sgi/python
# Edit CMIF movies interactively -- copy one or more files to an output file
# Possibilities:
#
# - convert between formats (grey, rgb, rgb8, ...)
# - change size
# - cut out a given area of the image
# - change time base (a la Vtime)
# - skip stretches of frames
import sys
import os
import gl, GL, DEVICE
import fl, FL
import flp
import Viewer
import getopt
import string
def main():
qsize = 20
opts, args = getopt.getopt(sys.argv[1:], 'q:')
for o, a in opts:
if o == '-q':
qsize = string.atoi(a)
ed = Editor().init(qsize)
if args[0:]:
ed.open_input(args[0])
if args[1:]:
ed.open_output(args[1])
while 1:
dummy = fl.do_forms()
class Editor:
def init(self, qsize):
self.qsize = qsize
self.vin = None
self.vout = None
self.ifile = ''
self.ofile = ''
formdef = flp.parse_form('VeditForm', 'form')
flp.create_full_form(self, formdef)
self.form.show_form(FL.PLACE_SIZE, FL.TRUE, 'Vedit')
fl.set_event_call_back(self.do_event)
return self
def do_event(self, (dev, val)):
if dev == DEVICE.REDRAW:
if self.vin:
self.vin.redraw(val)
if self.vout:
self.vout.redraw(val)
def iocheck(self):
self.msg('')
if self.vin == None and self.vout == None:
self.err('Please open input and output files first')
return 0
return self.icheck() and self.ocheck()
def icheck(self):
self.msg('')
if self.vin == None:
self.err('Please open an input file first')
return 0
return 1
def ocheck(self):
self.msg('')
if self.vout == None:
self.err('Please open an output file first')
return 0
return 1
def cb_in_new(self, args):
self.msg('')
hd, tl = os.path.split(self.ifile)
filename = fl.file_selector('Input video file', hd, '', tl)
if not filename: return
self.open_input(filename)
def cb_in_close(self, args):
self.msg('')
self.close_input()
def cb_in_skip(self, args):
if not self.icheck(): return
if not self.vin.get(): self.err('End of input file')
self.ishow()
def cb_in_back(self, args):
if not self.icheck(): return
if not self.vin.backup(): self.err('Input buffer exhausted')
self.ishow()
def cb_in_rewind(self, args):
if not self.icheck(): return
self.vin.rewind()
self.ishow()
def cb_copy(self, args):
if not self.iocheck(): return
data = self.vin.get()
if data:
if self.vout.getinfo() <> self.vin.getinfo():
print 'Copying info...'
self.vout.setinfo(self.vin.getinfo())
self.vout.put(data)
self.oshow()
self.ishow()
def cb_uncopy(self, args):
if not self.iocheck(): return
if not self.vout.backup():
self.err('Output buffer exhausted')
return
self.oshow()
if not self.vin.backup():
self.err('Input buffer exhausted')
return
self.ishow()
def cb_out_new(self, args):
self.msg('')
hd, tl = os.path.split(self.ofile)
filename = fl.file_selector('Output video file', hd, '', tl)
if not filename: return
self.open_output(filename)
def cb_out_close(self, args):
self.msg('')
self.close_output()
def cb_out_skip(self, arg):
if not self.ocheck(): return
if not self.vout.forward(): self.err('Output buffer exhausted')
self.oshow()
def cb_out_back(self, args):
if not self.ocheck(): return
if not self.vout.backup(): self.err('Output buffer exhausted')
self.oshow()
def cb_out_rewind(self, args):
if not self.ocheck(): return
self.vout.rewind()
self.oshow()
def cb_quit(self, args):
self.close_input()
self.close_output()
sys.exit(0)
def open_input(self, filename):
self.ifile = filename
basename = os.path.split(filename)[1]
title = 'in: ' + basename
try:
vin = Viewer.InputViewer().init(filename, \
title, self.qsize)
except:
self.err('Can\'t open input file', filename)
return
self.close_input()
self.vin = vin
self.in_file.label = basename
self.ishow()
def close_input(self):
if self.vin:
self.msg('Closing input file...')
self.vin.close()
self.msg('')
self.vin = None
self.in_file.label = '(none)'
self.format('in')
def ishow(self):
self.vin.show()
self.format('in')
def open_output(self, filename):
self.ofile = filename
basename = os.path.split(filename)[1]
title = 'out: ' + basename
try:
vout = Viewer.OutputViewer().init(filename, \
title, self.qsize)
except:
self.err('Can\'t open output file', filename)
return
self.close_output()
self.vout = vout
self.out_file.label = basename
if self.vin:
self.vout.setinfo(self.vin.getinfo())
self.oshow()
def close_output(self):
if self.vout:
self.msg('Closing output file...')
self.vout.close()
self.msg('')
self.vout = None
self.out_file.label = '(none)'
self.format('out')
def oshow(self):
self.vout.show()
self.format('out')
def msg(self, *args):
str = string.strip(string.join(args))
self.msg_area.label = str
def err(self, *args):
gl.ringbell()
apply(self.msg, args)
def format(self, io):
v = getattr(self, 'v' + io)
if v == None:
left = right = pos = 0
else:
left, right = v.qsizes()
pos = v.tell()
left = pos - left
right = pos + right
getattr(self, io + '_info1').label = `left`
getattr(self, io + '_info2').label = `pos`
getattr(self, io + '_info3').label = `right`
main()
Magic: 12321
Internal Form Definition File
(do not change)
Number of forms: 1
=============== FORM ===============
Name: form
Width: 480.000000
Height: 350.000000
Number of Objects: 23
--------------------
class: 1
type: 1
box: 0.000000 0.000000 480.000000 350.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label:
name:
callback:
argument:
--------------------
class: 11
type: 4
box: 170.000000 110.000000 140.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: -> Copy ->
name:
callback: cb_copy
argument: 0
--------------------
class: 11
type: 4
box: 10.000000 110.000000 140.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: Forward
name:
callback: cb_in_skip
argument: 0
--------------------
class: 11
type: 0
box: 10.000000 10.000000 140.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: Rewind input
name:
callback: cb_in_rewind
argument: 0
--------------------
class: 11
type: 0
box: 330.000000 10.000000 140.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: Reset output
name:
callback: cb_out_rewind
argument: 0
--------------------
class: 11
type: 0
box: 10.000000 260.000000 80.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: Input file...
name:
callback: cb_in_new
argument: 0
--------------------
class: 11
type: 0
box: 330.000000 260.000000 80.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: Output file...
name:
callback: cb_out_new
argument: 0
--------------------
class: 2
type: 0
box: 10.000000 210.000000 140.000000 40.000000
boxtype: 6
colors: 47 47
alignment: 2
style: 0
size: 11.000000
lcol: 0
label: (none)
name: in_file
callback:
argument:
--------------------
class: 2
type: 0
box: 330.000000 210.000000 140.000000 40.000000
boxtype: 6
colors: 47 47
alignment: 2
style: 0
size: 11.000000
lcol: 0
label: (none)
name: out_file
callback:
argument:
--------------------
class: 2
type: 0
box: 10.000000 160.000000 30.000000 30.000000
boxtype: 6
colors: 47 47
alignment: 2
style: 0
size: 8.000000
lcol: 0
label:
name: in_info1
callback:
argument:
--------------------
class: 11
type: 0
box: 170.000000 260.000000 140.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: Quit
name:
callback: cb_quit
argument: 0
--------------------
class: 11
type: 4
box: 330.000000 60.000000 140.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: Back
name:
callback: cb_out_back
argument: 0
--------------------
class: 11
type: 4
box: 10.000000 60.000000 140.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: Back
name:
callback: cb_in_back
argument: 0
--------------------
class: 11
type: 4
box: 330.000000 110.000000 140.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: Forward
name:
callback: cb_out_skip
argument: 0
--------------------
class: 11
type: 4
box: 170.000000 60.000000 140.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: Uncopy
name:
callback: cb_uncopy
argument: 0
--------------------
class: 11
type: 0
box: 100.000000 260.000000 50.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: Close
name:
callback: cb_in_close
argument: 0
--------------------
class: 11
type: 0
box: 420.000000 260.000000 50.000000 40.000000
boxtype: 1
colors: 47 47
alignment: 4
style: 0
size: 11.000000
lcol: 0
label: Close
name:
callback: cb_out_close
argument: 0
--------------------
class: 2
type: 0
box: 10.000000 310.000000 460.000000 30.000000
boxtype: 6
colors: 47 47
alignment: 2
style: 0
size: 11.000000
lcol: 0
label: CMIF Video Editor, by Guido van Rossum
name: msg_area
callback:
argument:
--------------------
class: 2
type: 0
box: 50.000000 160.000000 60.000004 40.000000
boxtype: 6
colors: 47 47
alignment: 2
style: 0
size: 11.000000
lcol: 0
label:
name: in_info2
callback:
argument:
--------------------
class: 2
type: 0
box: 120.000000 160.000000 30.000000 30.000000
boxtype: 6
colors: 47 47
alignment: 2
style: 0
size: 8.000000
lcol: 0
label:
name: in_info3
callback:
argument:
--------------------
class: 2
type: 0
box: 330.000000 160.000000 30.000000 30.000000
boxtype: 6
colors: 47 47
alignment: 2
style: 0
size: 8.000000
lcol: 0
label:
name: out_info1
callback:
argument:
--------------------
class: 2
type: 0
box: 370.000000 160.000000 60.000004 40.000000
boxtype: 6
colors: 47 47
alignment: 2
style: 0
size: 11.000000
lcol: 0
label:
name: out_info2
callback:
argument:
--------------------
class: 2
type: 0
box: 440.000000 160.000000 30.000000 30.000000
boxtype: 6
colors: 47 47
alignment: 2
style: 0
size: 8.000000
lcol: 0
label:
name: out_info3
callback:
argument:
==============================
create_the_forms
import gl, GL
import VFile
import os
class InputViewer:
def init(self, filename, title, qsize):
try:
self.vin = VFile.VinFile().init(filename)
except (EOFError, VFile.Error):
raise IOError, 'bad video input file'
if not title:
title = os.path.split(filename)[1]
self.filename = filename
self.title = title
self.qsize = qsize
gl.foreground()
gl.prefsize(self.vin.width, self.vin.height)
self.wid = -1
self.reset()
return self
def close(self):
self.vin.close()
if self.wid > 0:
gl.winclose(self.wid)
def rewind(self):
self.vin.rewind()
self.reset()
def getinfo(self):
return self.vin.getinfo()
# Internal
def reset(self):
if self.wid > 0:
gl.winset(self.wid)
gl.clear()
self.vin.initcolormap()
self.queue = []
self.qindex = 0
self.lost = 0
self.lastt = 0
self.eofread = 0
# Internal
def fillq(self):
if self.qindex < len(self.queue) or self.eofread: return
try:
t, d, cd = self.vin.getnextframe()
except EOFError:
self.eofread = 1
return
dt = t - self.lastt
self.lastt = t
self.queue.append(dt, d, cd)
while len(self.queue) > self.qsize:
del self.queue[0]
self.qindex = self.qindex - 1
self.lost = self.lost + 1
def show(self):
if self.wid < 0:
gl.foreground()
gl.prefsize(self.vin.width, self.vin.height)
self.wid = gl.winopen(self.title)
gl.clear()
self.vin.initcolormap()
self.fillq()
gl.winset(self.wid)
if self.qindex >= len(self.queue):
gl.clear()
return
dt, d, cd = self.queue[self.qindex]
self.vin.showframe(d, cd)
def redraw(self, wid):
if wid == self.wid >= 0:
gl.winset(self.wid)
gl.reshapeviewport()
self.show()
def get(self):
if self.qindex >= len(self.queue):
self.fillq()
if self.eofread:
return None
item = self.queue[self.qindex]
self.qindex = self.qindex + 1
return item
def backup(self):
if self.qindex == 0:
return 0
self.qindex = self.qindex - 1
return 1
def tell(self):
return self.lost + self.qindex
def qsizes(self):
return self.qindex, len(self.queue) - self.qindex
class OutputViewer:
def init(self, filename, title, qsize):
try:
self.vout = VFile.VoutFile().init(filename)
except (EOFError, VFile.Error):
raise IOError, 'bad video output file'
if not title:
title = os.path.split(filename)[1]
self.filename = filename
self.title = title
self.qsize = qsize
gl.foreground()
self.wid = -1
self.reset()
return self
def close(self):
while self.queue:
self.flushq()
self.vout.close()
if self.wid > 0:
gl.winclose(self.wid)
def rewind(self):
info = self.vout.getinfo()
self.vout.close()
self.vout = VFile.VoutFile().init(self.filename)
self.vout.setinfo(info)
self.reset()
def getinfo(self):
return self.vout.getinfo()
def setinfo(self, info):
if info == self.getinfo(): return # No change
self.vout.setinfo(info)
if self.wid > 0:
gl.winclose(self.wid)
self.wid = -1
# Internal
def reset(self):
if self.wid > 0:
gl.winset(self.wid)
gl.clear()
self.vout.initcolormap()
self.queue = []
self.spares = []
self.written = 0
self.lastt = 0
# Internal
def flushq(self):
if self.written == 0:
self.vout.writeheader()
dt, d, cd = self.queue[0]
self.lastt = self.lastt + dt
self.vout.writeframe(self.lastt, d, cd)
del self.queue[0]
self.written = self.written + 1
def show(self):
if self.wid < 0:
gl.foreground()
gl.prefsize(self.vout.width, self.vout.height)
self.wid = gl.winopen(self.title)
gl.clear()
self.vout.initcolormap()
gl.winset(self.wid)
if not self.queue:
gl.clear()
return
dt, d, cd = self.queue[-1]
self.vout.showframe(d, cd)
def redraw(self, wid):
if wid == self.wid >= 0:
gl.winset(self.wid)
gl.reshapeviewport()
self.show()
def backup(self):
if len(self.queue) < 1: return 0
self.spares.insert(0, self.queue[-1])
del self.queue[-1]
return 1
def forward(self):
if not self.spares: return 0
self.queue.append(self.spares[0])
del self.spares[0]
return 1
def put(self, item):
self.queue.append(item)
self.spares = []
while len(self.queue) > self.qsize:
self.flushq()
def tell(self):
return self.written + len(self.queue)
def qsizes(self):
return len(self.queue), len(self.spares)
def test():
import sys
a = InputViewer().init(sys.argv[1], '')
b = OutputViewer().init(sys.argv[2], '')
b.setinfo(a.getinfo())
while 1:
a.show()
data = a.get()
if data is None:
break
b.put(data)
b.show()
while a.backup():
data = a.get()
b.put(data)
b.show()
if a.backup(): a.show()
while 1:
data = a.get()
if data is None:
break
b.put(data)
b.show()
a.show()
b.close()
......@@ -200,13 +200,15 @@ def playonce(vin):
vin.magnify = magnify
if threading:
MAXSIZE = 20 # Don't read ahead too much
import thread
queue = []
import Queue
queue = Queue.Queue().init(MAXSIZE)
stop = []
thread.start_new_thread(read_ahead, (vin, queue, stop))
# Get the read-ahead thread going
while len(queue) < 5 and None not in queue:
time.millisleep(10)
while queue.qsize() < MAXSIZE/2 and not stop:
time.millisleep(100)
tin = 0
told = 0
......@@ -227,21 +229,18 @@ def playonce(vin):
if debug: sys.stderr.write('\n')
if threading:
stop.append(None)
while len(stop) < 2:
time.millisleep(10)
while 1:
item = queue.get()
if item == None: break
return (dev != LEFTMOUSE)
if dev == REDRAW:
gl.reshapeviewport()
if data: vin.showframe(data, cdata)
if threading:
if not queue:
if debug: sys.stderr.write('.')
time.millisleep(10)
continue
q0 = queue[0]
if q0 == None: break
del queue[0]
tin, data, cdata = q0
if debug and queue.empty(): sys.stderr.write('.')
item = queue.get()
if item == None: break
tin, data, cdata = item
else:
try:
tin, size, csize = vin.getnextframeheader()
......@@ -301,13 +300,13 @@ def playonce(vin):
def read_ahead(vin, queue, stop):
try:
while not stop: queue.append(vin.getnextframe())
while not stop: queue.put(vin.getnextframe())
except EOFError:
queue.append(None)
pass
queue.put(None)
stop.append(None)
# Don't forget to call the main program
try:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment