You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sems/apps/ivr/IvrDialogBase.cpp

642 lines
16 KiB

#include "IvrDialogBase.h"
#include "IvrAudio.h"
#include "IvrAudioMixIn.h"
#include "Ivr.h"
#include "IvrSipDialog.h"
#include "IvrSipRequest.h"
#include "AmMediaProcessor.h"
/** \brief python wrapper of IvrDialog, the base class for python IVR sessions */
typedef struct {
PyObject_HEAD
PyObject* dialog;
PyObject* invite_req;
IvrDialog* p_dlg;
} IvrDialogBase;
// Constructor
static PyObject* IvrDialogBase_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"ivr_dlg", NULL};
IvrDialogBase *self;
self = (IvrDialogBase *)type->tp_alloc(type, 0);
if (self != NULL) {
PyObject* o_dlg = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &o_dlg)){
Py_DECREF(self);
return NULL;
}
if (!PyCObject_Check(o_dlg)){
Py_DECREF(self);
return NULL;
}
self->p_dlg = (IvrDialog*)PyCObject_AsVoidPtr(o_dlg);
// initialize self.dialog
self->dialog = IvrSipDialog_FromPtr(&self->p_dlg->dlg);
if(!self->dialog){
PyErr_Print();
ERROR("IvrDialogBase: while creating IvrSipDialog instance\n");
Py_DECREF(self);
return NULL;
}
// initialize self.invite_req
self->invite_req = IvrSipRequest_FromPtr(self->p_dlg->getInviteReq());
if(!self->invite_req){
PyErr_Print();
ERROR("IvrDialogBase: while creating IvrSipRequest instance for invite_req\n");
Py_DECREF(self);
return NULL;
}
}
DBG("IvrDialogBase_new\n");
return (PyObject *)self;
}
static void
IvrDialogBase_dealloc(IvrDialogBase* self)
{
DBG("IvrDialogBase_dealloc\n");
Py_XDECREF(self->dialog);
self->ob_type->tp_free((PyObject*)self);
}
//
// Event handlers
//
static PyObject* IvrDialogBase_onRtpTimeout(IvrDialogBase* self, PyObject*)
{
DBG("no script implementation for onRtpTimeout(). Stopping session. \n");
assert(self->p_dlg);
self->p_dlg->setStopped();
self->p_dlg->postEvent(0);
Py_INCREF(Py_None);
return Py_None;
}
// static PyObject* IvrDialogBase_onSessionStart(IvrDialogBase* self, PyObject*)
// {
// DBG("no script implementation for onSessionStart(self,hdrs) !!!\n");
// PyErr_SetNone(PyExc_NotImplementedError);
// return NULL; // no return value
// }
// static PyObject* IvrDialogBase_onBye(IvrDialogBase* self, PyObject*)
// {
// DBG("no script implementation for onBye(self) !!!\n");
// PyErr_SetNone(PyExc_NotImplementedError);
// return NULL; // no return value
// }
// static PyObject* IvrDialogBase_onEmptyQueue(IvrDialogBase* self, PyObject*)
// {
// DBG("no script implementation for onEmptyQueue(self) !!!\n");
// PyErr_SetNone(PyExc_NotImplementedError);
// return NULL; // no return value
// }
// static PyObject* IvrDialogBase_onDtmf(IvrDialogBase* self, PyObject* args)
// {
// int key, duration;
// if(!PyArg_ParseTuple(args,"ii",&key,&duration))
// return NULL;
// DBG("IvrDialogBase_onDtmf(%i,%i)\n",key,duration);
// Py_INCREF(Py_None);
// return Py_None;
// }
// static PyObject* IvrDialogBase_onTimer(IvrDialogBase* self, PyObject* args)
// {
// DBG("IvrDialog::onTimer: no script implementation!!!\n");
// PyErr_SetNone(PyExc_NotImplementedError);
// return NULL; // no return value
// }
// static PyObject* IvrDialogBase_onOtherBye(IvrDialogBase* self, PyObject*)
// {
// DBG("IvrDialogBase_onOtherBye()\n");
// Py_INCREF(Py_None);
// return Py_None;
// }
// static PyObject* IvrDialogBase_onOtherReply(IvrDialogBase* self, PyObject* args)
// {
// DBG("IvrDialogBase_onOtherReply()\n");
// int code;
// char* reason;
// if(!PyArg_ParseTuple(args,"is",&code,&reason))
// return NULL;
// Py_INCREF(Py_None);
// return Py_None;
// }
//
// Call control
//
static PyObject* IvrDialogBase_stopSession(IvrDialogBase* self, PyObject*)
{
assert(self->p_dlg);
self->p_dlg->setStopped();
self->p_dlg->postEvent(0);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_dropSession(IvrDialogBase* self, PyObject*)
{
assert(self->p_dlg);
self->p_dlg->drop();
self->p_dlg->postEvent(0);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_bye(IvrDialogBase* self, PyObject*)
{
assert(self->p_dlg);
self->p_dlg->dlg.bye();
Py_INCREF(Py_None);
return Py_None;
}
//
// Media control
//
static PyObject* IvrDialogBase_enqueue(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
PyObject *o_play, *o_rec;
AmAudio *a_play=NULL;
AmAudioFile *a_rec=NULL;
if(!PyArg_ParseTuple(args,"OO",&o_play,&o_rec))
return NULL;
if (o_play != Py_None){
if(PyObject_TypeCheck(o_play,&IvrAudioFileType)){
((IvrAudioFile*)o_play)->af->rewind();
a_play = ((IvrAudioFile*)o_play)->af;
} else if(PyObject_TypeCheck(o_play,&IvrAudioMixInType)){
a_play = ((IvrAudioMixIn*)o_play)->mix;
} else {
PyErr_SetString(PyExc_TypeError,"Argument 1 is no IvrAudioFile");
return NULL;
}
}
if (o_rec != Py_None){
if(!PyObject_TypeCheck(o_rec,&IvrAudioFileType)){
PyErr_SetString(PyExc_TypeError,"Argument 2 is no IvrAudioFile");
return NULL;
}
a_rec = ((IvrAudioFile*)o_rec)->af;
}
self->p_dlg->playlist.addToPlaylist(new AmPlaylistItem(a_play,a_rec));
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_flush(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
self->p_dlg->playlist.close();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_queueIsEmpty(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
return PyBool_FromLong(self->p_dlg->playlist.isEmpty());
}
static PyObject* IvrDialogBase_mute(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
self->p_dlg->setMute(true);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_unmute(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
self->p_dlg->setMute(false);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_remove_mediaprocessor(IvrDialogBase* self,
PyObject* args)
{
assert(self->p_dlg);
AmMediaProcessor::instance()->removeSession(self->p_dlg);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_add_mediaprocessor(IvrDialogBase* self,
PyObject* args)
{
assert(self->p_dlg);
AmMediaProcessor::instance()->addSession(self->p_dlg,
self->p_dlg->getCallgroup());
Py_INCREF(Py_None);
return Py_None;
}
// DTMF
static PyObject* IvrDialogBase_enableDTMFDetection(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
self->p_dlg->setDtmfDetectionEnabled(true);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_disableDTMFDetection(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
self->p_dlg->setDtmfDetectionEnabled(false);
Py_INCREF(Py_None);
return Py_None;
}
// B2B methods
static PyObject* IvrDialogBase_b2b_connectCallee(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
string remote_party, remote_uri, local_party, local_uri;
PyObject* py_o;
if((PyArg_ParseTuple(args,"O",&py_o)) && (py_o == Py_None)) {
DBG("args == Py_None\n");
remote_party = self->p_dlg->getOriginalRequest().to;
remote_uri = self->p_dlg->getOriginalRequest().r_uri;
} else {
DBG("args != Py_None\n");
char* rp = 0; char* ru = 0; char* lp = 0; char* lu = 0;
if(!PyArg_ParseTuple(args,"ss|ss",&rp, &ru, &lp, &lu))
return NULL;
else {
remote_party = string(rp);
remote_uri = string(ru);
if (lp && lu) {
local_party = string(lp);
local_uri = string(lu);
}
}
}
self->p_dlg->connectCallee(remote_party, remote_uri, local_party, local_uri);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_b2b_set_relayonly(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
self->p_dlg->set_sip_relay_only(true);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_b2b_set_norelayonly(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
self->p_dlg->set_sip_relay_only(false);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_b2b_terminate_leg(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
self->p_dlg->terminateLeg();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_b2b_terminate_other_leg(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
self->p_dlg->terminateOtherLeg();
Py_INCREF(Py_None);
return Py_None;
}
// Timer methods
static PyObject* IvrDialogBase_setTimer(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
int id = 0, interval = 0;
if(!PyArg_ParseTuple(args,"ii",&id, &interval))
return NULL;
if (id <= 0) {
ERROR("IVR script tried to set timer with non-positive ID.\n");
return NULL;
}
AmArg di_args,ret;
di_args.push(id);
di_args.push(interval);
di_args.push(self->p_dlg->getLocalTag().c_str());
self->p_dlg->user_timer->
invoke("setTimer", di_args, ret);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_removeTimer(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
int id = 0;
if(!PyArg_ParseTuple(args,"i",&id))
return NULL;
if (id <= 0) {
ERROR("IVR script tried to remove timer with non-positive ID.\n");
return NULL;
}
AmArg di_args,ret;
di_args.push(id);
di_args.push(self->p_dlg->getLocalTag().c_str());
self->p_dlg->user_timer->
invoke("removeTimer",di_args,ret);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* IvrDialogBase_removeTimers(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
AmArg di_args,ret;
di_args.push(self->p_dlg->getLocalTag().c_str());
self->p_dlg->user_timer->
invoke("removeUserTimers",di_args,ret);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject*
IvrDialogBase_getinvite_req(IvrDialogBase *self, void *closure)
{
Py_INCREF(self->invite_req);
return self->invite_req;
}
static PyObject*
IvrDialogBase_getdialog(IvrDialogBase *self, void *closure)
{
Py_INCREF(self->dialog);
return self->dialog;
}
static PyObject*
IvrDialogBase_redirect(IvrDialogBase *self, PyObject* args)
{
assert(self->p_dlg);
char* refer_to=0;
if(!PyArg_ParseTuple(args,"s",&refer_to))
return NULL;
if(self->p_dlg->transfer(refer_to)){
ERROR("redirect failed\n");
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef IvrDialogBase_methods[] = {
// Event handlers
{"onRtpTimeout", (PyCFunction)IvrDialogBase_onRtpTimeout, METH_NOARGS,
"Gets called on RTP timeout"
},
// {"onSessionStart", (PyCFunction)IvrDialogBase_onSessionStart, METH_VARARGS,
// "Gets called on session start"
// },
// {"onBye", (PyCFunction)IvrDialogBase_onBye, METH_NOARGS,
// "Gets called if we received a BYE"
// },
// {"onEmptyQueue", (PyCFunction)IvrDialogBase_onEmptyQueue, METH_NOARGS,
// "Gets called when the audio queue runs out of items"
// },
// {"onDtmf", (PyCFunction)IvrDialogBase_onDtmf, METH_VARARGS,
// "Gets called when dtmf have been received"
// },
// {"onTimer", (PyCFunction)IvrDialogBase_onTimer, METH_VARARGS,
// "Gets called when a timer is fired"
// },
// Call control
{"stopSession", (PyCFunction)IvrDialogBase_stopSession, METH_NOARGS,
"Stop the session"
},
{"bye", (PyCFunction)IvrDialogBase_bye, METH_NOARGS,
"Send a BYE"
},
{"redirect", (PyCFunction)IvrDialogBase_redirect, METH_VARARGS,
"Refers the remote party to some third party."
},
{"dropSession", (PyCFunction)IvrDialogBase_dropSession, METH_NOARGS,
"Drop the session and forget it without replying"
},
// Media control
{"enqueue", (PyCFunction)IvrDialogBase_enqueue, METH_VARARGS,
"Add some audio to the queue (mostly IvrAudioFile)"
},
{"queueIsEmpty", (PyCFunction)IvrDialogBase_queueIsEmpty, METH_NOARGS,
"Is the audio queue empty?"
},
{"flush", (PyCFunction)IvrDialogBase_flush, METH_NOARGS,
"Flush the queue"
},
{"mute", (PyCFunction)IvrDialogBase_mute, METH_NOARGS,
"mute the RTP stream (don't send packets)"
},
{"unmute", (PyCFunction)IvrDialogBase_unmute, METH_NOARGS,
"unmute the RTP stream (send packets)"
},
{"connectMedia", (PyCFunction)IvrDialogBase_add_mediaprocessor, METH_NOARGS,
"enable the processing of audio and RTP"
},
{"disconnectMedia", (PyCFunction)IvrDialogBase_remove_mediaprocessor, METH_NOARGS,
"disable the processing of audio and RTP"
},
// DTMF
{"enableDTMFDetection", (PyCFunction)IvrDialogBase_enableDTMFDetection, METH_NOARGS,
"enable the dtmf detection"
},
{"disableDTMFDetection", (PyCFunction)IvrDialogBase_disableDTMFDetection, METH_NOARGS,
"disable the dtmf detection"
},
// B2B
{"connectCallee", (PyCFunction)IvrDialogBase_b2b_connectCallee, METH_VARARGS,
"call given party as (new) callee,"
"if remote_party and remote_uri are empty (None),"
"we will connect to the callee of the initial caller request"
},
{"terminateLeg", (PyCFunction)IvrDialogBase_b2b_terminate_leg, METH_VARARGS,
"Terminate our leg and forget the other"
},
{"terminateOtherLeg", (PyCFunction)IvrDialogBase_b2b_terminate_other_leg, METH_VARARGS,
"Terminate the other leg and forget it"
},
{"setRelayonly", (PyCFunction)IvrDialogBase_b2b_set_relayonly, METH_NOARGS,
"sip requests will be relayed, and not processed"
},
{"setNoRelayonly", (PyCFunction)IvrDialogBase_b2b_set_norelayonly, METH_NOARGS,
"sip requests will be processed"
},
// Timers
{"setTimer", (PyCFunction)IvrDialogBase_setTimer, METH_VARARGS,
"set a timer with id and t seconds timeout"
},
{"removeTimer", (PyCFunction)IvrDialogBase_removeTimer, METH_VARARGS,
"remove a timer by id"
},
{"removeTimers", (PyCFunction)IvrDialogBase_removeTimers, METH_NOARGS,
"remove all timers"
},
{NULL} /* Sentinel */
};
static PyGetSetDef IvrDialogBase_getset[] = {
{"dialog",
(getter)IvrDialogBase_getdialog, NULL,
"the dialog property",
NULL},
{"invite_req",
(getter)IvrDialogBase_getinvite_req, NULL,
"the initial invite request",
NULL},
{NULL} /* Sentinel */
};
PyTypeObject IvrDialogBaseType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"ivr.IvrDialogBase", /*tp_name*/
sizeof(IvrDialogBase), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)IvrDialogBase_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"Base class for IvrDialog", /*tp_doc*/
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
IvrDialogBase_methods, /* tp_methods */
0, /* tp_members */
IvrDialogBase_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
IvrDialogBase_new, /* tp_new */
};