# $Id$ # # This file is part of ivam2. # # ivam2 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. # # ivam2 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 ivam2; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. import os, sys, time, select, signal, gzip import ivamCore, ivamApi, ivamUtil pc = None def sigterm(*args): pc.quit = 1 class PipeConnector(ivamApi.Connector): BUFSIZE = 128 stdin = sys.stdin stdout = sys.stdout playing = False recording = False timeout = 0 quit = False umask = 0007 def __init__(self, processor): if ivamCore.DEBUG: ivamCore.log("PipeConnector()") global pc pc = self signal.signal(signal.SIGTERM, sigterm) self.callerNumber = os.getenv("CALLERMSN") self.ringNumber = os.getenv("RINGMSN") self.processor = processor try: s = os.fstat(128) self.pipeHack = True ivamCore.log("Found and enabled pipe hack.") except OSError: self.pipeHack = False ivamCore.log("Pipe hack not detected.") def openDtmf(self): try: fn = os.environ["DTMFFIFO"] except KeyError: self.dtmfFifo = None return self.dtmfFifo = file(fn, "rb") def playClip(self, fname): self.stopPlayback() if ivamCore.DEBUG: ivamCore.log("playClip('%s')" % fname) self.playFile = ivamUtil.magicFile(fname, "rb") self.playName = fname self.playing = True self.playBuffer = None def stopPlayback(self): if ivamCore.DEBUG: ivamCore.log("stopPlayback()") if self.playing: self.playFile.close() self.playing = False def stopPlayback2(self): self.stopPlayback() self.processor.onClipFinish(self, self.playName) def recordClip(self, fname, z = False): self.stopRecording() if ivamCore.DEBUG: ivamCore.log("recordClip('%s')" % fname) u = os.umask(self.umask) try: if z: self.recordFile = gzip.open(fname, "w+b") else: self.recordFile = open(fname, "w+b") finally: os.umask(u) self.recordName = fname self.recording = True self.recordLength = 0 def stopRecording(self): if ivamCore.DEBUG: ivamCore.log("stopRecording()") if self.recording: self.recordFile.close() self.recording = False self.processor.onRecordFinish(self, self.recordName, self.recordLength) def setTimeout(self, t): if ivamCore.DEBUG: ivamCore.log("timeout(%u)" % t) if t: self.timeout = time.time()+t else: self.timeout = 0 def run(self): if ivamCore.DEBUG: ivamCore.log("run()") self.openDtmf() self.processor.onConnect(self, self.callerNumber, self.ringNumber) self.loop() self.stopPlayback() self.stopRecording() self.processor.onHangup(self) if not self.dtmfFifo is None: self.dtmfFifo.close() if ivamCore.DEBUG: ivamCore.log("run() finished") def hangup(self): if ivamCore.DEBUG: ivamCore.log("hangup()") self.quit = True def loop(self): while not self.quit: t = None now = time.time() if self.timeout: t = self.timeout - now if t < 0: t = 0 o = [] i = [self.stdin] if not self.dtmfFifo is None: i += [self.dtmfFifo] if self.playing: o += [self.stdout] if t is None: i, o, x = select.select(i, o, []) else: i, o, x = select.select(i, o, [], t) now = time.time() if self.timeout and self.timeout < now: self.processor.onTimeout(self) self.timeout = 0 if self.quit: break # Check DTMF fifo if not self.dtmfFifo is None and self.dtmfFifo in i: self.handleDtmf() if self.quit: break # Check STDOUT if self.stdout in o: self.writeStdout() if self.quit: break # Check STDIN if self.stdin in i: self.readStdin() if self.quit: break def readStdin(self): buf = os.read(self.stdin.fileno(), self.BUFSIZE) if buf == "": self.quit = 1 elif self.recording: self.recordFile.write(buf) self.recordLength += len(buf) def writeStdout(self): if not self.playing: return if self.playBuffer is None: self.playBuffer = self.playFile.read(self.BUFSIZE) # EOF? if len(self.playBuffer) == 0: self.stopPlayback2() return c = os.write(self.stdout.fileno(), self.playBuffer) self.playBuffer = self.playBuffer[c:] if len(self.playBuffer) == 0: self.playBuffer = None def handleDtmf(self): if not self.dtmfFifo is None: d = self.dtmfFifo.read(1) if d == "": self.dtmfFifo.close() self.dtmfFifo = None else: self.processor.onDtmfEvent(self, d) def flushOutput(self): if not self.pipeHack: return try: b = os.read(128, 4096) if ivamCore.DEBUG: ivamCore.log("Pipe hack succeeded") except OSError: if ivamCore.DEBUG: ivamCore.log("Pipe hack failed")