#!/usr/bin/env python ## ## pyvnc2swf - vnc2swf.py ## ## $Id: vnc2swf.py,v 1.20 2006/02/09 09:39:18 euske Exp $ ## ## Copyright (C) 2005 by Yusuke Shinyama (yusuke at cs . nyu . edu) ## All Rights Reserved. ## ## "No X11" changes copyright (C) 2006 by Reid Ellis ## All Rights Reserved. ## ## This is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This software is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this software; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ## USA. ## import sys, os, time, socket, re from struct import pack, unpack import threading from movie import SWFInfo from output import SWFShapeStream, SWFVideoStream from rfb import RFBError, RFBNetworkClient, RFBNetworkClientForRecording, RFBStreamConverter stderr = sys.stderr ## RFBNetworkClientWithTkMixin ## class RFBNetworkClientWithTkMixin: def tk_init(self, root): self.root = root self.doloop = True return def interrupt(self): self.doloop = False return def loop(self): self.doloop = True while self.doloop: self.root.update() if not self.loop1(): break self.finish_update() return self def getpass(self): pass # return tkPasswordDialog('Login', # 'Password for %s:%d' % (self.host, self.port), # self.root).result class RFBNetworkClientWithTk(RFBNetworkClientWithTkMixin, RFBNetworkClient): pass class RFBNetworkClientForRecordingWithTk(RFBNetworkClientWithTkMixin, RFBNetworkClientForRecording): pass def vnc2swf(info, outtype='shape', host='localhost', port=5900, preferred_encoding=(0,), subprocess=None, pwdfile=None, debug=0, merge=False): if outtype in ('shape','video'): if outtype == 'shape': stream = SWFShapeStream(info) else: stream = SWFVideoStream(info) converter = RFBStreamConverter(info, stream) client = RFBNetworkClient(host, port, converter, pwdfile=pwdfile, preferred_encoding=preferred_encoding) else: client = RFBNetworkClientForRecording(host, port, info.filename, pwdfile=pwdfile, preferred_encoding=preferred_encoding) try: client.init().auth().start() if debug: print 'start recording' if subprocess: subprocess.start() try: try: client.loop() except KeyboardInterrupt: pass finally: if debug: print 'stop recording' if subprocess: subprocess.stop() client.close() stream.close() info.write_html() except socket.error, e: print >>stderr, 'Socket error:', e except RFBError, e: print >>stderr, 'RFB error:', e # Contributed by David Fraser if merge: tmpfile = os.tempnam(os.path.dirname(info.filename), "vncmerge-") + os.path.basename(info.filename) print "renaming %s to %s for merge" % (info.filename, tmpfile) if os.path.exists(tmpfile): os.remove(tmpfile) os.rename( info.filename, tmpfile ) try: # TODO: sort out getting outputfilename properly audiofilename = subprocess.outputfile import edit args = ["-d", "-o", info.filename, "-a", audiofilename, tmpfile] if not edit.main(args): print >>stderr, "Error doing merge..." finally: origexists, tmpexists = os.path.exists(info.filename), os.path.exists(tmpfile) print "origexists %r, tmpexists %r" % (origexists, tmpexists) if origexists and tmpexists: try: os.remove(tmpfile) except OSError, e: print >>stderr, "Could not remove temporary file: %s" % e elif tmpexists: print >>stderr, "only tmpfile remains after merge, renaming to original (but will not contain sound)" os.rename( tmpfile, info.filename ) return # Thread management class RecordingThread: def __init__(self, outputfile): try: import record_sound except ImportError, e: print "unable to use pymedia?:", e raise self.outputfile = outputfile self.recorder = record_sound.voiceRecorder(self.outputfile) self.thread = threading.Thread(target=self.recorder.run) def start(self): self.thread.start() def stop(self): self.recorder.finished = True self.thread.join() # Subprocess management class Subprocess: def __init__(self, s): try: import subprocess except ImportError: print >>stderr, '-S option requires Python 2.4 or newer.' sys.exit(111) if not hasattr(os, 'kill'): print >>stderr, '-S option works only on Unix or Mac OS X.' sys.exit(111) self.args = s.split(' ') self.popen = None return def start(self): import subprocess self.popen = subprocess.Popen(self.args) return def stop(self): import signal os.kill(self.popen.pid, signal.SIGINT) self.popen.wait() return # main # ./vnc2swf.py -S 'arecord -t wav -c 1 -r 22050 out.wav' -n -o out.swf def main(args): import getopt def usage(): print ("usage: vnc2swf.py [-d] [-n] [-o filename] [-t {shape|video|vnc}]" \ " [-e encoding] [-N] [-C clipping] [-r framerate] [-z] [-m] [-a]" \ " [-S subprocess] [-P pwdfile] [host[:display] [port]]") sys.exit(2) try: (opts, args) = getopt.getopt(sys.argv[1:], 'dno:t:e:NC:r:S:P:zma') except getopt.GetoptError: usage() (debug, console, outtype, subprocess, merge, pwdfile) = (0, False, None, None, False, None) (cursor, host, port, preferred_encoding) = (True, 'localhost', 5900, (0,)) info = SWFInfo() for (k, v) in opts: if k == '-d': debug += 1 elif k == '-n': console = True elif k == '-t': outtype = v elif k == '-e': preferred_encoding = tuple([ int(i) for i in v.split(',') ]) elif k == '-N': cursor = False elif k == '-S': subprocess = Subprocess(v) elif k == '-a': subprocess = RecordingThread(v) elif k == '-m': merge = True elif k == '-P': pwdfile = v elif k == '-o': info.filename = v elif k == '-C': try: info.set_clipping(v) except ValueError: print >>stderr, 'Invalid clipping specification:', v usage() elif k == "-r": info.framerate = int(v) elif k == "-z": info.set_scalable(True) if not outtype: if info.filename: if info.filename.endswith('.vnc'): outtype = 'vnc' elif info.filename.endswith('.swf'): outtype = 'shape' else: outtype = 'shape' if outtype not in ('shape','video','vnc'): print 'Please specify the output type or file extension.' usage() if cursor: preferred_encoding += (-232,-239,) if 1 <= len(args): if ':' in args[0]: i = args[0].index(':') host = args[0][:i] or 'localhost' port = int(args[0][i+1:])+5900 else: host = args[0] if 2 <= len(args): port = int(args[1]) if not info.filename: print 'Please specify the output filename.' usage() vnc2swf(info, outtype, host, port, preferred_encoding=preferred_encoding, subprocess=subprocess, pwdfile=pwdfile, merge=merge, debug=debug) if __name__ == "__main__": main(sys.argv[1:])