[asterisk-commits] mjordan: testsuite/asterisk/trunk r2953 - /asterisk/trunk/lib/python/asterisk/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Dec 22 14:46:42 CST 2011
Author: mjordan
Date: Thu Dec 22 14:46:40 2011
New Revision: 2953
URL: http://svnview.digium.com/svn/testsuite?view=rev&rev=2953
Log:
Add confbridge base class for ConfBridge tests
Somehow forget to check this in as well with the previous test check-in.
(issue ASTERISK-19059)
Added:
asterisk/trunk/lib/python/asterisk/confbridge.py (with props)
Added: asterisk/trunk/lib/python/asterisk/confbridge.py
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/lib/python/asterisk/confbridge.py?view=auto&rev=2953
==============================================================================
--- asterisk/trunk/lib/python/asterisk/confbridge.py (added)
+++ asterisk/trunk/lib/python/asterisk/confbridge.py Thu Dec 22 14:46:40 2011
@@ -1,0 +1,191 @@
+#!/usr/bin/env python
+# vim: sw=3 et:
+'''
+Copyright (C) 2011, Digium, Inc.
+Matt Jordan <mjordan at digium.com>
+
+This program is free software, distributed under the terms of
+the GNU General Public License Version 2.
+'''
+
+import sys
+import os
+import glob
+import shutil
+import logging
+
+from TestCase import TestCase
+from TestState import TestState
+from TestState import TestStateController
+from twisted.internet import reactor
+
+sys.path.append("lib/python")
+
+logger = logging.getLogger(__name__)
+
+class ConfbridgeChannelObject:
+ """
+ A tracking object that ties together information about the channels
+ involved in a ConfBridge
+ """
+
+ def __init__(self, conf_bridge_channel, caller_channel, caller_ami, profile_option = ""):
+ """
+ conf_bridge_channel The channel inside the Asterisk instance hosting the ConfBridge
+ caller_channel The channel inside the Asterisk instance that called the ConfBridge server
+ caller_ami An AMI connection back to the calling Asterisk instance
+ profile_option Some string field that identifies the profile set for the conf_bridge_channel
+ """
+ self.conf_bridge_channel = conf_bridge_channel
+ self.caller_channel = caller_channel
+ self.caller_ami = caller_ami
+ self.profile = profile_option
+
+class ConfbridgeTestState(TestState):
+ """
+ Base class test state for ConfBridge. Allows states to send DTMF tones, audio files,
+ hangup, and otherwise interact with the conference. As this inherits from TestState, this
+ is also an entry in the state engine, such that it will receive test event notifications.
+ Derived classes should handle these state notifications, and use the methods in this class
+ to respond accordingly.
+ """
+
+ def __init__(self, controller, testCase, calls = {}):
+ """
+ controller The TestStateController managing the test
+ testCase The main test object
+ calls A dictionary (keyed by conf_bridge_channel ID) of ConfbridgeChannelObjects
+ """
+ TestState.__init__(self, controller)
+ self.testCase = testCase
+ self.calls = calls
+ self.__previous_dtmf = {}
+ self.__previous_audio = {}
+ if (len(self.calls) > 0):
+ for k in self.calls:
+ self.__previous_dtmf[k] = ""
+ self.__previous_audio[k] = ""
+
+ logger.debug(" Entering state [" + self.getStateName() + "]")
+
+ def registerNewCaller(self, channel_object):
+ """
+ Register a new ConfbridgeChannelObject with the state engine
+ channel_object An object that ties all of the various channels / AMI information together
+ """
+ if not (channel_object.conf_bridge_channel in self.calls):
+ self.calls[channel_object.conf_bridge_channel] = channel_object
+ self.__previous_dtmf[channel_object.conf_bridge_channel] = ""
+ self.__previous_audio[channel_object.conf_bridge_channel] = ""
+
+ def getStateName(self):
+ """
+ Should be overriden by derived classes and return the name of the current state
+ """
+ pass
+
+ def handleDefaultState(self, event):
+ """
+ Can be called by derived classes to output a state that is being ignored
+ """
+ logger.debug(" State [" + self.getStateName() + "] - ignoring state change " + event['state'])
+
+ def __handleRedirectFailure__(self, reason):
+ logger.warn("Error sending redirect - test may or may not fail:")
+ logger.warn(reason.getTraceback())
+ return reason
+
+ def hangup(self, call_id):
+ """
+ Hangs up the current call
+ call_id The channel name
+ """
+ if call_id in self.calls:
+ df = self.calls[call_id].caller_ami.redirect(self.calls[call_id].caller_channel, "caller", "hangup", 1)
+ df.addErrback(self.__handleRedirectFailure__)
+ else:
+ logger.warn("Unknown call ID %s" % call_id)
+
+ def sendDTMF(self, call_id, dtmfToSend):
+ """
+ Send a DTMF signal to the server
+ call_id The channel name, from the perspective of the ConfBridge app
+ dtmfToSend The DTMF code to send
+ """
+ if call_id in self.calls:
+ logger.debug("Attempting to send DTMF %s via %s", dtmfToSend, call_id)
+ if (self.__previous_dtmf[call_id] != dtmfToSend):
+ self.calls[call_id].caller_ami.setVar(channel = self.calls[call_id].caller_channel, variable = "DTMF_TO_SEND", value = dtmfToSend)
+ self.__previous_dtmf[call_id] = dtmfToSend
+ """
+ Redirect to the DTMF extension - note that we assume that we only have one channel to
+ the other asterisk instance
+ """
+ df = self.calls[call_id].caller_ami.redirect(self.calls[call_id].caller_channel, "caller", "sendDTMF", 1)
+ df.addErrback(self.__handleRedirectFailure__)
+ else:
+ logger.warn("Unknown call ID %s" % call_id)
+
+ def sendSoundFile(self, call_id, audioFile):
+ """
+ Send a sound file to the server
+ call_id The channel name, from the perspective of the ConfBridge app
+ audioFile The local path to the file to stream
+ """
+ if call_id in self.calls:
+ logger.debug("Attempting to send audio file %s via %s", audioFile, call_id)
+ if (self.__previous_audio[call_id] != audioFile):
+ self.calls[call_id].caller_ami.setVar(channel = call_id, variable = "TALK_AUDIO", value = audioFile)
+ self.__previous_audio[call_id] = audioFile
+ """
+ Redirect to the send sound file extension - note that we assume that we only have one channel to
+ the other asterisk instance
+ """
+ df = self.calls[call_id].caller_ami.redirect(self.calls[call_id].caller_channel, "caller", "sendAudio", 1)
+ df.addErrback(self.__handleRedirectFailure__)
+ else:
+ logger.warn("Unknown call ID %s" % call_id)
+
+ def sendSoundFileWithDTMF(self, call_id, audioFile, dtmfToSend):
+ """
+ Send a sound file to the server, then send a DTMF signal
+ audioFile The local path to the file to stream
+ dtmfToSend The DTMF signal to send
+
+ Note that this is necessary so that when the audio file is finished, we close the audio recording cleanly;
+ otherwise, Asterisk may detect the end of file as a hangup
+ """
+ if call_id in self.calls:
+ logger.debug("Attempting to send audio file %s followed by %s via %s", audioFile, dtmfToSend, call_id)
+ if (self.__previous_audio[call_id] != audioFile):
+ self.calls[call_id].caller_ami.setVar(channel = self.calls[call_id].caller_channel, variable = "TALK_AUDIO", value = audioFile)
+ self.__previous_audio[call_id] = audioFile
+ if (self.__previous_dtmf[call_id] != dtmfToSend):
+ self.calls[call_id].caller_ami.setVar(channel = self.calls[call_id].caller_channel, variable = "DTMF_TO_SEND", value = dtmfToSend)
+ self.__previous_dtmf[call_id] = dtmfToSend
+ """
+ Redirect to the send sound file extension - note that we assume that we only have one channel to
+ the other asterisk instance
+ """
+ df = self.calls[call_id].caller_ami.redirect(self.calls[call_id].caller_channel, "caller", "sendAudioWithDTMF", 1)
+ df.addErrback(self.__handleRedirectFailure__)
+ else:
+ logger.warn("Unknown call ID %s" % call_id)
+
+ def scheduleDTMF(self, delay, call_id, dtmfToSend):
+ """
+ Schedule and send a DTMF tone sometime later
+ delay The number of seconds to wait
+ call_id The channel name, from the perspective of the ConfBridge app
+ dtmfToSend The DTMF code to send
+ """
+ reactor.callLater(delay, self.sendDTMF, call_id, dtmfToSend)
+
+ def scheduleSendSoundFile(self, delay, call_id, audioFile):
+ """
+ Schedule and send a DTMF tone sometime later
+ delay The number of seconds to wait
+ call_id The channel name, from the perspective of the ConfBridge app
+ audioFile The local path to the file to stream
+ """
+ reactor.callLater(delay, self.sendSoundFile, call_id, audioFile)
Propchange: asterisk/trunk/lib/python/asterisk/confbridge.py
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: asterisk/trunk/lib/python/asterisk/confbridge.py
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: asterisk/trunk/lib/python/asterisk/confbridge.py
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the asterisk-commits
mailing list