From 2076ab0ce49b934ce287ff9a863d4b8885946dec Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 6 Jan 2004 00:54:58 +0000 Subject: ulaw files, more python work git-svn-id: file:///home/lennart/svn/public/ivam2/trunk@16 dbf6933d-3bce-0310-9bcc-ed052ba35b35 --- client/ivam-autobox | 57 ++++++++++++ client/ivam-createvb | 4 + client/ivam-voicebox | 21 +++-- client/ivamApi.py | 9 +- client/ivamCore.py | 15 ++- client/ivamDefs.py | 3 +- client/ivamPipeConnector.py | 221 ++++++++++++++++++++++++++++++++++++++++++++ client/ivamUtil.py | 29 +++++- client/ivamVoiceBox.py | 72 +++++++-------- ulaw/auth.ulaw.gz | Bin 0 -> 30073 bytes ulaw/authok.ulaw.gz | Bin 0 -> 26541 bytes ulaw/beep.ulaw.gz | Bin 0 -> 581 bytes ulaw/empty.ulaw.gz | Bin 0 -> 27733 bytes ulaw/nomoremessages.ulaw.gz | Bin 0 -> 23405 bytes ulaw/removed.ulaw.gz | Bin 0 -> 17263 bytes ulaw/welcome.ulaw.gz | Bin 0 -> 39514 bytes 16 files changed, 373 insertions(+), 58 deletions(-) create mode 100644 client/ivamPipeConnector.py create mode 100644 ulaw/auth.ulaw.gz create mode 100644 ulaw/authok.ulaw.gz create mode 100644 ulaw/beep.ulaw.gz create mode 100644 ulaw/empty.ulaw.gz create mode 100644 ulaw/nomoremessages.ulaw.gz create mode 100644 ulaw/removed.ulaw.gz create mode 100644 ulaw/welcome.ulaw.gz diff --git a/client/ivam-autobox b/client/ivam-autobox index 8d5063a..2713347 100755 --- a/client/ivam-autobox +++ b/client/ivam-autobox @@ -1,2 +1,59 @@ #!/usr/bin/python +import sys, os, getopt + +from ivamCore import log +import ivamCore, ivamVoiceBox + +def usage(): + log("%s [--record-time=SECS] [--pin=PIN] [--pin-file=PINFILE] [--debug] [DIRECTORY]" % sys.argv[0]) + +def parseArgs(vb, argv): + + try: + opts, args = getopt.getopt(argv[1:], "ht:p:P:de:", ["help", "record-time=", "pin=", "pin-file=", "debug", "message-program"]) + except getopt.GetoptError: + usage() + sys.exit(1) + + recordTime = 60 + pin = "-" + + for o, a in opts: + if o in ("-d", "--debug"): + ivamCore.DEBUG = True + + elif o in ("-h", "--help"): + usage() + sys.exit() + + elif o in ("-t", "--record-time"): + recordTime = int(a) + + elif o in ("-p", "--pin"): + pin = a + + elif o in ("-P", "--pin-file"): + pin = getContents(a) + + dname = "msn-" + sys.getenv("RINGMSN") + + if len(args): + dname = args[0] + "/" + dname + + try: + ivamVoiceBox.setupVoiceBox(dname, pin, recordTime) + except OSError: + pass + + vb.setDirectory(dname) + +def main(): + vb = ivamVoiceBox.VoiceBox() + parseArgs(vb, sys.argv) + ivamCore.newConnector(vb).run() + sys.exit() + +if __name__ == "__main__": + main() + diff --git a/client/ivam-createvb b/client/ivam-createvb index 8d5063a..7365db6 100755 --- a/client/ivam-createvb +++ b/client/ivam-createvb @@ -1,2 +1,6 @@ #!/usr/bin/python +import ivamVoiceBox + +ivamVoiceBox.setupVoiceBox("lennart") + diff --git a/client/ivam-voicebox b/client/ivam-voicebox index fc7b45a..fbf6afa 100755 --- a/client/ivam-voicebox +++ b/client/ivam-voicebox @@ -1,26 +1,32 @@ #!/usr/bin/python -import sys, os +import sys, os, getopt from ivamCore import log import ivamCore, ivamVoiceBox -def usage(self): - log("%s [--record-time=SECS] [--pin=PIN] [--pin-file=PINFILE] [--debug]", sys.argv[0]) +def usage(): + log("%s [--record-time=SECS] [--pin=PIN] [--pin-file=PINFILE] [--message-program=BINARY] [--debug] DIRECTORY" % sys.argv[0]) def parseArgs(vb, argv): try: - opts, args = getopt.getopt(argv[1:], "ht:p:P:de:", ["help", "record-time=", "pin=", "pin-file=", "debug", "message"]) + opts, args = getopt.getopt(argv[1:], "ht:p:P:de:", ["help", "record-time=", "pin=", "pin-file=", "debug", "message-program"]) except getopt.GetoptError: usage() sys.exit(1) - vb.setDirectory(args[0]) + try: + dname = args[0] + except IndexError: + usage() + sys.exit(1) + + vb.setDirectory(dname) for o, a in opts: if o in ("-d", "--debug"): - DEBUG = True + ivamCore.DEBUG = True elif o in ("-h", "--help"): usage() @@ -35,9 +41,10 @@ def parseArgs(vb, argv): elif o in ("-P", "--pin-file"): vb.setPin(getContents(a)) - elif o in ("-e", "--message"): + elif o in ("-e", "--message-program"): vb.messageProgram = a + def main(): vb = ivamVoiceBox.VoiceBox() parseArgs(vb, sys.argv) diff --git a/client/ivamApi.py b/client/ivamApi.py index 3cf5651..3fc86b3 100644 --- a/client/ivamApi.py +++ b/client/ivamApi.py @@ -1,7 +1,7 @@ class Processor: - def onConnect(self, c): + def onConnect(self, c, callerNumber, ringNumber): pass def onHangup(self, c): @@ -30,10 +30,7 @@ class Connector: def stopPlayback(self): pass - def softStopPlayback(self): - pass - - def recordClip(self, fname, gzip = 0): + def recordClip(self, fname, gzip = False): pass def stopRecording(self): @@ -42,3 +39,5 @@ class Connector: def timeout(self, t): pass + def hangup(self, t): + pass diff --git a/client/ivamCore.py b/client/ivamCore.py index 08d8771..a091bc0 100644 --- a/client/ivamCore.py +++ b/client/ivamCore.py @@ -1,12 +1,17 @@ -import os, ivamShbufConnector, ivamPipeConnector; +import sys, os -def newConnector(c): +import ivamPipeConnector - if getenv("SHBUF") is None: - return ivamPipeConnector(c) +DEBUG = True + +def newConnector(p): + + if os.getenv("SHBUF") is None: + return ivamPipeConnector.PipeConnector(p) else: - return ivamShbufConnector(c) + return None +# return ShbufConnector(c) def log(s): sys.stderr.write("%s\n" % s) diff --git a/client/ivamDefs.py b/client/ivamDefs.py index 45c5087..0804e45 100644 --- a/client/ivamDefs.py +++ b/client/ivamDefs.py @@ -1,2 +1,3 @@ -spoolDirectory = "/var/spool/ivam" +spoolDirectory = "/home/lennart/tmp/ivam-spool" +shareDirectory = "/home/lennart/projects/ivam-reloaded/ulaw" diff --git a/client/ivamPipeConnector.py b/client/ivamPipeConnector.py new file mode 100644 index 0000000..ff0be5f --- /dev/null +++ b/client/ivamPipeConnector.py @@ -0,0 +1,221 @@ + +import os, sys, time, select, signal + +import ivamCore, ivamApi, ivamUtil + +pc = None + +def sigterm(*args): + pc.quit = 1 + +class PipeConnector(ivamApi.Connector): + + BUFSIZE = 128 + + sdtin = sys.stdin + stdout = sys.stdout + + playing = False + recording = False + + timeout = 0 + quit = False + + 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 + + def openDtmf(self): + + try: + fn = os.environ["DTMFFIFO"] + except KeyError: + self.dtmfFifo = None + return + + self.dtmfFifo = file.open(fn, "rb") + + def playClip(self, fname): + + if ivamCore.DEBUG: + ivamCore.log("playClip('%s')" % fname) + + self.stopPlayback() + + 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 + + processor.onClipFinish(self, self.playName) + + def recordClip(self, fname, gzip = False): + + if ivamCore.DEBUG: + ivamCore.log("recordClip('%s')" % fname) + + self.stopRecording() + + if gzip: + self.recordFile = gzip.open(fname, "w+b") + else: + self.recordFile = open(fname, "w+b") + + self.recordName = fname + self.recording = True + + def stopRecording(self): + + if ivamCore.DEBUG: + ivamCore.log("stopRecording()") + + if self.recording: + self.recordFile.close() + self.recording = False + + processor.onRecordFinish(self, self.recordName) + + def timeout(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) + 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: + + if ivamCore.DEBUG: + ivamCore.log("iteration") + + 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 = select.select(i, o, []) + else: + i, o = select.select(i, o, [], t) + + now = time.time() + + if self.timeout < now: + processor.onTimeout() + 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 o: + 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) + + + 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.stopPlayback() + return + + c = os.write(self.stdout.fileno(), self.playBuffer) + self.playBuffer = self.playBuffer[c:] + + if len(self.playBuffer) == 0: + self.playBuffer = None + + def dtmfCheck(self): + + if not self.dtmfFifo is None: + + d = self.dtmfFifoFd.read(1) + + if d == "": + self.dtmfFifo.close() + self.dtmfFifo = None + else: + self.onDtmfEvent(self, d) diff --git a/client/ivamUtil.py b/client/ivamUtil.py index 17e9801..053638e 100644 --- a/client/ivamUtil.py +++ b/client/ivamUtil.py @@ -1,13 +1,36 @@ +import gzip + def getContents(fn): - f = file(a, "r") - r = f.readline().strip(" \t\r\n")) + f = file(fn, "r") + r = f.readline().strip(" \t\r\n") f.close() return r def setContents(fn, s): - f = file(a, "w") + f = file(fn, "w") f.write("%s\n" % s) f.close() +def magicFile(fn, mode): + + f = None + + try: + f = gzip.open(fn, mode) + f.read(1) + f.seek(0) + return f + + except IOError: + + if not f is None: + f.close() + + return open(fn, mode) + + + + + diff --git a/client/ivamVoiceBox.py b/client/ivamVoiceBox.py index 3cafab1..9217005 100644 --- a/client/ivamVoiceBox.py +++ b/client/ivamVoiceBox.py @@ -1,12 +1,9 @@ -import getopt, sys +import getopt, sys, os import ivamApi, ivamCore, ivamDefs -from ivamCore import log from ivamUtil import getContents, setContents -DEBUG = False - class VoiceBox(ivamApi.Processor): # Constants @@ -15,17 +12,15 @@ class VoiceBox(ivamApi.Processor): # State currentState = STATE_INVALID + fileSuffix = ".ulaw.gz" - # Use GZIP compression? - useGzip = 1 - - def onConnect(self, c, callerNumber, calleeNumber): + def onConnect(self, c, callerNumber, ringNumber): - if DEBUG: - log("onConnect()") + if ivamCore.DEBUG: + ivamCore.log("onConnect()") self.callerNumber = callerNumber - self.calleeNumber = calleeNumber + self.ringNumber = ringNumber self.currentState = self.STATE_WELCOME c.playClip("welcome") @@ -43,8 +38,8 @@ class VoiceBox(ivamApi.Processor): def onClipFinish(self, c, fname): - if DEBUG: - log("onClipFinish('%s')" % fname) + if ivamCore.DEBUG: + ivamCore.log("onClipFinish('%s')" % fname) if self.currentState == self.STATE_WELCOME: self.currentState = self.STATE_WELCOME_BEEP; @@ -52,7 +47,7 @@ class VoiceBox(ivamApi.Processor): elif self.currentState == self.STATE_WELCOME_BEEP: self.currentState = self.STATE_RECORD - c.recordClip(self.nextMessageName(), self.useGzip) + c.recordClip(self.nextMessageName(), True) c.setTimeout(self.recordTime) elif self.currentState == self.STATE_PRE_FINISH: @@ -117,7 +112,7 @@ class VoiceBox(ivamApi.Processor): def onDtmfEvent(self, c, event): - if DEBUG: + if ivamCore.DEBUG: ivamCore.log("onDtmfEvent(%c)" % event) if ((self.currentState == self.STATE_WELCOME) or (self.currentState == self.STATE_WELCOME_BEEP)) and (event == '0'): @@ -159,7 +154,7 @@ class VoiceBox(ivamApi.Processor): if self.currentMessage >= len(self.messages): self.currentMessage = len(self.messages)-1 - os.remove("%s.ulaw" % self.messages[self.currentMessage]) + os.remove(self.messages[self.currentMessage]) del(self.messages[self.currentMessage]) self.currentState = self.STATE_REMOVED @@ -200,7 +195,7 @@ class VoiceBox(ivamApi.Processor): def onTimeout(self, c): - if DEBUG: + if ivamCore.DEBUG: ivamCore.log("onTimeout()") if self.currentState == self.STATE_RECORD: @@ -214,54 +209,54 @@ class VoiceBox(ivamApi.Processor): def onRecordFinish(self, c, fname): - if DEBUG: + if ivamCore.DEBUG: ivamCore.log("onRecordFinish(%s)", fname) - log("Starting new message notification program.") - r = os.spawnvp(os.P_WAIT, self.messageProgram, [self.messageProgram, "%s.ulaw" % fname]) - log("Program finished (return value is %i)." % r) + ivamCore.log("Starting new message notification program.") + r=os.spawnvp(os.P_WAIT, self.messageProgram, (self.messageProgram, fname)) + ivamCore.log("Program finished (return value is %i)." % r) def getMessageNames(self): - f = filter(lambda e: e.startswith("message-"), os.listdir(self.directory)) + f = os.listdir(self.messageDirectory) f.sort() f.reverse() return f def nextMessageName(self): - fn = "%s/message-%010i-%s-%s.ulaw" % (self.directory, time.time(), self.callerNumber, self.callerNumber) - - if self.useGzip: - return fn+".gz" - - return fn + return "%s/%010i-%s-%s%s" % (self.messageDirectory, time.time(), self.callerNumber, self.callerNumber, self.fileSuffix) def setPin(self, pin): if re.match('^([0-9#*]*|-)$', pin).end() is None: - log("Invalid PIN. PIN has to consist of 0-9#*. Use '-' for always denying access.") + ivamCore.log("Invalid PIN. PIN has to consist of 0-9#*. Use '-' for always denying access.") raise Exception, "Invalid PIN" self.pin = pin - def setDirectory(self, path): + def setDirectory(self, dname): + if dname.find("/") == -1: + dname = "%s/%s" % (ivamDefs.spoolDirectory, dname) - self.directory = path + self.directory = dname + self.messageDirectory = dname + "/messages" try: - self.setPin(getContents("%s/PIN" % path)) + self.setPin(getContents("%s/PIN" % dname)) except Exception: self.pin = "-" try: - self.recordTime = int(getContents("%s/RECORD_TIME" % path))) + self.recordTime = int(getContents("%s/RECORD_TIME" % dname)) except Exception: self.recordTime = 60 - messageProgram = "%s/NEWMESSAGE" % path + messageProgram = "%s/newmessage" % dname + -def setupVoiceBox(dname, pin, recordTime): + +def setupVoiceBox(dname, pin = "-", recordTime = 60): if dname.find("/") == -1: dname = "%s/%s" % (ivamDefs.spoolDirectory, dname) @@ -271,5 +266,8 @@ def setupVoiceBox(dname, pin, recordTime): setContents("%s/PIN" % dname, pin) setContents("%s/RECORD_TIME" % dname, `recordTime`) - os.symlink - + ulaw = map(lambda e: e+".ulaw.gz", ('welcome', 'beep', 'empty', 'nomoremessages', 'auth', 'authok', 'removed')) + + for f in ulaw + ['newmessage', 'README']: + os.symlink("%s/%s" % (ivamDefs.shareDirectory, f), "%s/%s" % (dname, f)) + diff --git a/ulaw/auth.ulaw.gz b/ulaw/auth.ulaw.gz new file mode 100644 index 0000000..8b6e677 Binary files /dev/null and b/ulaw/auth.ulaw.gz differ diff --git a/ulaw/authok.ulaw.gz b/ulaw/authok.ulaw.gz new file mode 100644 index 0000000..fa6d389 Binary files /dev/null and b/ulaw/authok.ulaw.gz differ diff --git a/ulaw/beep.ulaw.gz b/ulaw/beep.ulaw.gz new file mode 100644 index 0000000..c7000c0 Binary files /dev/null and b/ulaw/beep.ulaw.gz differ diff --git a/ulaw/empty.ulaw.gz b/ulaw/empty.ulaw.gz new file mode 100644 index 0000000..3fed27e Binary files /dev/null and b/ulaw/empty.ulaw.gz differ diff --git a/ulaw/nomoremessages.ulaw.gz b/ulaw/nomoremessages.ulaw.gz new file mode 100644 index 0000000..6682b8b Binary files /dev/null and b/ulaw/nomoremessages.ulaw.gz differ diff --git a/ulaw/removed.ulaw.gz b/ulaw/removed.ulaw.gz new file mode 100644 index 0000000..c09b11b Binary files /dev/null and b/ulaw/removed.ulaw.gz differ diff --git a/ulaw/welcome.ulaw.gz b/ulaw/welcome.ulaw.gz new file mode 100644 index 0000000..5b90e30 Binary files /dev/null and b/ulaw/welcome.ulaw.gz differ -- cgit