summaryrefslogtreecommitdiffstats
path: root/client/ivamVoiceBox.py
diff options
context:
space:
mode:
Diffstat (limited to 'client/ivamVoiceBox.py')
-rw-r--r--client/ivamVoiceBox.py275
1 files changed, 275 insertions, 0 deletions
diff --git a/client/ivamVoiceBox.py b/client/ivamVoiceBox.py
new file mode 100644
index 0000000..3cafab1
--- /dev/null
+++ b/client/ivamVoiceBox.py
@@ -0,0 +1,275 @@
+
+import getopt, sys
+import ivamApi, ivamCore, ivamDefs
+
+from ivamCore import log
+from ivamUtil import getContents, setContents
+
+DEBUG = False
+
+class VoiceBox(ivamApi.Processor):
+
+ # Constants
+ STATE_INVALID, STATE_WELCOME, STATE_WELCOME_BEEP, STATE_RECORD, STATE_PRE_FINISH, STATE_FINISH, STATE_AUTH, STATE_MESSAGE, STATE_AUTH_OK, STATE_NO_MORE_MESSAGES, STATE_MESSAGE_BEEP, STATE_REMOVED, STATE_EMPTY = range(13)
+ AUTH_TIMEOUT = 20
+
+ # State
+ currentState = STATE_INVALID
+
+ # Use GZIP compression?
+ useGzip = 1
+
+ def onConnect(self, c, callerNumber, calleeNumber):
+
+ if DEBUG:
+ log("onConnect()")
+
+ self.callerNumber = callerNumber
+ self.calleeNumber = calleeNumber
+
+ self.currentState = self.STATE_WELCOME
+ c.playClip("welcome")
+
+ def loginComplete(self):
+ self.messages = self.getMessageNames()
+ self.currentMessage = 0
+
+ if len(self.messages) == 0:
+ self.currentState = self.STATE_EMPTY
+ c.playClip("empty")
+ else:
+ self.currentState = self.STATE_MESSAGE_BEEP
+ c.playClip("beep")
+
+ def onClipFinish(self, c, fname):
+
+ if DEBUG:
+ log("onClipFinish('%s')" % fname)
+
+ if self.currentState == self.STATE_WELCOME:
+ self.currentState = self.STATE_WELCOME_BEEP;
+ c.playClip("beep")
+
+ elif self.currentState == self.STATE_WELCOME_BEEP:
+ self.currentState = self.STATE_RECORD
+ c.recordClip(self.nextMessageName(), self.useGzip)
+ c.setTimeout(self.recordTime)
+
+ elif self.currentState == self.STATE_PRE_FINISH:
+ self.currentState = self.STATE_FINISH
+ c.hangup()
+
+ elif self.currentState == self.STATE_AUTH:
+
+ # Silence ...
+ pass
+
+ elif self.currentState == self.STATE_AUTH_OK:
+
+ self.loginComplete()
+
+ elif self.currentState == self.STATE_MESSAGE_BEEP:
+
+ while True:
+
+ if self.currentMessage >= len(self.messages):
+ self.currentMessage = self.STATE_NO_MORE_MESSAGES
+ c.playClip("nomoremessages")
+ else:
+ self.currentState = self.STATE_MESSAGE_BEEP
+
+ try:
+ c.playClip(self.messages[self.currentMessage])
+ break
+
+ except IOError, e:
+ del(self.messages[self.currentMessage])
+
+ if len(self.messages) == 0:
+ self.currentState = self.STATE_EMPTY
+ c.playClip("empty")
+
+ continue
+
+ elif self.currentState == self.STATE_MESSAGE:
+
+ self.currentMessage +=1
+ self.currentState = self.STATE_MESSAGE_BEEP
+ c.playClip("beep")
+
+ elif self.currentState == self.STATE_REMOVE:
+
+ if len(self.messages) == 0:
+ self.currentState = self.STATE_EMPTY
+ c.playClip("empty")
+ else:
+ self.currentState = self.STATE_MESSAGE_BEEP
+ c.playClip("beep")
+
+ elif self.currentState == self.STATE_NO_MORE_MESSAGES:
+
+ # Silence ...
+ pass
+
+ elif self.currentState == self.STATE_EMPTY:
+ self.currentState = self.STATE_FINISH
+ c.hangup()
+
+ def onDtmfEvent(self, c, event):
+
+ if DEBUG:
+ ivamCore.log("onDtmfEvent(%c)" % event)
+
+ if ((self.currentState == self.STATE_WELCOME) or (self.currentState == self.STATE_WELCOME_BEEP)) and (event == '0'):
+
+ if self.pin == "":
+ self.loginComplete()
+
+ elif self.pin == "-":
+ self.currentState = self.STATE_FINISH
+ c.hangup()
+
+ else:
+ self.currentState = self.STATE_AUTH
+ self.inputPin = ""
+ c.stopPlayback()
+ c.playClip("auth")
+ c.setTimeout(AUTH_TIMEOUT)
+
+ elif self.currentState == self.STATE_AUTH:
+ c.stopPlayback()
+ self.inputPin += event
+
+ if len(self.inputPin) >= len(self.pin):
+ c.setTimeout(0)
+
+ if self.inputPin == self.pin:
+ self.currentState = self.STATE_AUTH_OK
+ c.playClip("authok")
+ else:
+ self.currentState = self.STATE_FINISH
+ c.hangup()
+
+ elif self.currentState in [self.STATE_MESSAGE, self.STATE_MESSAGE_BEEP, self.STATE_NO_MORE_MESSAGES] :
+
+ changed = 0
+
+ if event == '0':
+
+ if self.currentMessage >= len(self.messages):
+ self.currentMessage = len(self.messages)-1
+
+ os.remove("%s.ulaw" % self.messages[self.currentMessage])
+ del(self.messages[self.currentMessage])
+
+ self.currentState = self.STATE_REMOVED
+ c.playClip("removed")
+
+ else:
+ if event in ['4', '2']:
+ self.currentMessage -= 1
+ changed = 1
+
+ if event in ['6', '8']:
+ self.currentMessage += 1
+ changed = 1
+
+ if event == '5':
+ changed = 1
+
+ if event == '1':
+ self.currentMessage = 0
+ changed = 1
+
+ if event == '7':
+ self.currentMessage = len(self.messages)-1
+ changed = 1
+
+ if self.currentMessage < 0:
+ self.currentMessage = 0
+
+ if self.currentMessage >= len(self.messages):
+ self.currentMessage = len(self.messages)-1
+
+ if changed:
+ self.currentState = self.STATE_MESSAGE_BEEP
+ c.playClip("beep")
+
+ else:
+ c.stopPlayback()
+
+ def onTimeout(self, c):
+
+ if DEBUG:
+ ivamCore.log("onTimeout()")
+
+ if self.currentState == self.STATE_RECORD:
+ self.currentState = self.STATE_PRE_FINISH
+ c.stopRecording()
+ c.playClip("beep")
+
+ elif self.currentState in [self.STATE_AUTH, self.STATE_PIN2, self.STATE_PIN3, self.STATE_PIN4]:
+ self.currentState = self.STATE_FINISH
+ c.hangup()
+
+ def onRecordFinish(self, c, fname):
+
+ if 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)
+
+ def getMessageNames(self):
+
+ f = filter(lambda e: e.startswith("message-"), os.listdir(self.directory))
+ 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
+
+ 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.")
+ raise Exception, "Invalid PIN"
+
+ self.pin = pin
+
+ def setDirectory(self, path):
+
+ self.directory = path
+
+ try:
+ self.setPin(getContents("%s/PIN" % path))
+ except Exception:
+ self.pin = "-"
+
+ try:
+ self.recordTime = int(getContents("%s/RECORD_TIME" % path)))
+ except Exception:
+ self.recordTime = 60
+
+ messageProgram = "%s/NEWMESSAGE" % path
+
+def setupVoiceBox(dname, pin, recordTime):
+ if dname.find("/") == -1:
+ dname = "%s/%s" % (ivamDefs.spoolDirectory, dname)
+
+ os.mkdir(dname, 0770)
+ os.mkdir("%s/messages" % dname, 0770)
+
+ setContents("%s/PIN" % dname, pin)
+ setContents("%s/RECORD_TIME" % dname, `recordTime`)
+
+ os.symlink
+