# -*- coding: utf-8 -*- # Copyright 2012 Ariel Calzada - ariel@activitycentral.com # # This program 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 program 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 program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import subprocess import os import gobject import os import signal import popen2 import fcntl import re import signal class ScreencastProcess(gobject.GObject): """ Process handler """ # Attributes _args = None _childprocess = None _childpid = None _childtimer = None _encodingtimer = None _encodingstream = None _encodingpid = None # Custom signals __gsignals__ = { 'encode-start': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()), 'encode-finished': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()), 'update-statusbar': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING,gobject.TYPE_FLOAT,)), } def __init__(self): """ Constructor """ super(ScreencastProcess, self).__init__() self._args = [] self._ch_err = "" def runProcess(self, q, s, fp): """ Run program """ self._ch_err = "" # cmd programName = "recordmydesktop" fname = "/usr/bin/" + programName if not os.path.isfile(fname): fname = "./" + programName self._args.append ( fname ) # Output file self._args.append ( "-o" ) self._args.append ( fp ) # FPS - Framerate self._args.append ( "--fps" ) self._args.append ( "15" ) self._args.append ( "--quick-subsampling" ) self._args.append ( "--no-frame" ) # Overwrite self._args.append("--overwrite") # Encode on the fly #self._args.append("--on-the-fly-encoding") # Quality if str(q) == "2": self._args.append("-v_quality") self._args.append("0") elif str(q) == "1": self._args.append("-v_quality") self._args.append("31") # Sound if not s: self._args.append("--no-sound") # Start program self._childprocess = popen2.Popen3 ( self._args, "t", 0 ) flags = fcntl.fcntl(self._childprocess.childerr, fcntl.F_GETFL) fcntl.fcntl(self._childprocess.childerr, fcntl.F_SETFL, flags | os.O_NONBLOCK) self._childpid = self._childprocess.pid # Check process every second self._childtimer = gobject.timeout_add (1000, self.checkProcessStatus) def checkProcessStatus(self): """ Check the current status of the process """ # Not running if self._childpid == None: return False """ os.waitpid(pid, options) On Unix: Wait for completion of a child process given by process id pid, and return a tuple containing its process id and exit status indication (encoded as for wait()). The semantics of the call are affected by the value of the integer options, which should be 0 for normal operation. If pid is greater than 0, waitpid() requests status information for that specific process. If pid is 0, the request is for the status of any child in the process group of the current process. If pid is -1, the request pertains to any child of the current process. If pid is less than -1, status is requested for any process in the process group -pid (the absolute value of pid). An OSError is raised with the value of errno when the syscall returns -1. ---------------------------------------------------------------- os.WNOHANG The option for waitpid() to return immediately if no child process status is available immediately. The function returns (0, 0) in this case. """ # Get process status process_status = os.waitpid ( self._childpid, os.WNOHANG ) process_status_id = process_status [ 0 ] # Not running if process_status_id != 0: self._childpid = None return False return True def monitorEncoding(self): """ Monitor encoding """ strstdout = "" try: strstdout = self._encodingstream.read() if strstdout == "": self.emit('encode-finished') return False except: return True try: percentage = float ( strstdout.replace("[","").replace("%] ","") ) except: percentage = 0.0 if percentage > 100.0: percentage = 100.0 percentage_raw = percentage percentage = "%.2f%%" % ( percentage ) self.emit('update-statusbar',percentage, percentage_raw) return True def stopProcess(self): """ Stop process """ # Stop timer if self._childtimer != None: gobject.source_remove(self._childtimer) self._childtimer = None # Get process status process_status = os.waitpid ( self._childpid, os.WNOHANG ) process_status_id = process_status [ 0 ] # Running if process_status_id == 0: # Start encoding os.kill(self._childpid, signal.SIGTERM) # Monitor encoding self.emit('encode-start') self._encodingstream = self._childprocess.fromchild self._encodingpid = self._childpid flags = fcntl.fcntl(self._encodingstream, fcntl.F_GETFL) fcntl.fcntl(self._encodingstream, fcntl.F_SETFL, flags | os.O_NONBLOCK) self._encodingtimer = gobject.timeout_add ( 100, self.monitorEncoding ) self._childpid = None