From 8e491874ce2f52d050b9fc4caf7a42044a6f4ac8 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 9 Jun 2006 09:21:05 +0000 Subject: [PATCH] * fixed bug in Makefile concerning missing python files compilation. * added python event handlers for onOtherBye, onOtherReply. * improved event handlers bootstrap: by returning True, a python event handler can choose to let the default c++ implementation beeing called. git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@55 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- apps/ivr/Ivr.cpp | 134 ++++++++++++++++++++++++++++--------- apps/ivr/Ivr.h | 7 +- apps/ivr/IvrDialogBase.cpp | 119 +++++++++++++++++++------------- apps/ivr/Makefile | 3 +- 4 files changed, 178 insertions(+), 85 deletions(-) diff --git a/apps/ivr/Ivr.cpp b/apps/ivr/Ivr.cpp index 5b11a177..d76b1b7e 100644 --- a/apps/ivr/Ivr.cpp +++ b/apps/ivr/Ivr.cpp @@ -440,60 +440,130 @@ void IvrDialog::setPyPtrs(PyObject *mod, PyObject *dlg) Py_INCREF(py_dlg); } -void IvrDialog::callPyEventHandler(char* name) +static PyObject * +type_error(const char *msg) { + PyErr_SetString(PyExc_TypeError, msg); + return NULL; +} - PyObject* o = PyObject_CallMethod(py_dlg,name,NULL); - Py_XDECREF(o); - - if(!o) - PyErr_Print(); +static PyObject * +null_error(void) +{ + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_SystemError, + "null argument to internal routine"); + return NULL; } -void IvrDialog::callPyEventHandler(char* name, int id) +PyObject * +PyObject_VaCallMethod(PyObject *o, char *name, char *format, va_list va) { + PyObject *args, *func = 0, *retval; - PYLOCK; - PyObject* o = PyObject_CallMethod(py_dlg,name, "i",id); - Py_XDECREF(o); - - if(!o) - PyErr_Print(); + if (o == NULL || name == NULL) + return null_error(); + + func = PyObject_GetAttrString(o, name); + if (func == NULL) { + PyErr_SetString(PyExc_AttributeError, name); + return 0; + } + + if (!PyCallable_Check(func)) + return type_error("call of non-callable attribute"); + + if (format && *format) { + args = Py_VaBuildValue(format, va); + } + else + args = PyTuple_New(0); + + if (!args) + return NULL; + + if (!PyTuple_Check(args)) { + PyObject *a; + + a = PyTuple_New(1); + if (a == NULL) + return NULL; + if (PyTuple_SetItem(a, 0, args) < 0) + return NULL; + args = a; + } + + retval = PyObject_Call(func, args, NULL); + + Py_DECREF(args); + Py_DECREF(func); + + return retval; } -void IvrDialog::callPyEventHandler(char* name, const string& str) +bool IvrDialog::callPyEventHandler(char* name, char* fmt, ...) { + bool ret=false; + va_list va; PYLOCK; - PyObject* o = PyObject_CallMethod(py_dlg,name, "s",str.c_str()); - Py_XDECREF(o); - - if(!o) + + va_start(va, fmt); + PyObject* o = PyObject_VaCallMethod(py_dlg,name,fmt,va); + va_end(va); + + if(!o) { + + if(PyErr_ExceptionMatches(PyExc_AttributeError)){ + + DBG("method %s is not implemented, trying default one\n",name); + return true; + } + PyErr_Print(); + } + else { + if(o && PyBool_Check(o) && (o == Py_True)) { + + ret = true; + } + + Py_DECREF(o); + } + + return ret; } void IvrDialog::onSessionStart(const AmSipRequest& req) { - PYLOCK; - callPyEventHandler("onSessionStart",req.hdrs); + callPyEventHandler("onSessionStart","s",req.hdrs.c_str()); setInOut(&playlist,&playlist); AmB2BCallerSession::onSessionStart(req); } void IvrDialog::onBye(const AmSipRequest& req) { - PYLOCK; - callPyEventHandler("onBye"); + if(callPyEventHandler("onBye",NULL)) + AmB2BSession::onBye(req); } void IvrDialog::onDtmf(int event, int duration_msec) { - PYLOCK; - PyObject* o = PyObject_CallMethod(py_dlg,"onDtmf","ii",event,duration_msec); - Py_XDECREF(o); - - if(!o) - PyErr_Print(); + if(callPyEventHandler("onDtmf","ii",event,duration_msec)) + AmB2BSession::onDtmf(event,duration_msec); +} + +void IvrDialog::onOtherBye(const AmSipRequest& req) +{ + if(callPyEventHandler("onOtherBye",NULL)) + AmB2BSession::onOtherBye(req); +} + +void IvrDialog::onOtherReply(const AmSipReply& r) +{ + if(callPyEventHandler("onOtherReply","is", + r.code,r.reason.c_str())) + AmB2BSession::onOtherReply(r); } void IvrDialog::process(AmEvent* event) @@ -502,15 +572,15 @@ void IvrDialog::process(AmEvent* event) AmAudioEvent* audio_event = dynamic_cast(event); if(audio_event && audio_event->event_id == AmAudioEvent::noAudio){ - PYLOCK; - callPyEventHandler("onEmptyQueue"); + + callPyEventHandler("onEmptyQueue", NULL); event->processed = true; } AmPluginEvent* plugin_event = dynamic_cast(event); if(plugin_event && plugin_event->name == "timer_timeout") { - PYLOCK; - callPyEventHandler("onTimer", plugin_event->data.get(0).asInt()); + + callPyEventHandler("onTimer", "i", plugin_event->data.get(0).asInt()); event->processed = true; } diff --git a/apps/ivr/Ivr.h b/apps/ivr/Ivr.h index f8cab9af..057c084f 100644 --- a/apps/ivr/Ivr.h +++ b/apps/ivr/Ivr.h @@ -101,9 +101,7 @@ class IvrDialog : public AmB2BCallerSession PyObject *py_mod; PyObject *py_dlg; - void callPyEventHandler(char* name); - void callPyEventHandler(char* name, int id); - void callPyEventHandler(char* name, const string& str); + bool callPyEventHandler(char* name, char* fmt, ...); void process(AmEvent* event); @@ -120,6 +118,9 @@ public: void onSessionStart(const AmSipRequest& req); void onBye(const AmSipRequest& req); void onDtmf(int event, int duration_msec); + + void onOtherBye(const AmSipRequest& req); + void onOtherReply(const AmSipReply& r); }; #endif diff --git a/apps/ivr/IvrDialogBase.cpp b/apps/ivr/IvrDialogBase.cpp index 1ba4eaf3..9621d704 100644 --- a/apps/ivr/IvrDialogBase.cpp +++ b/apps/ivr/IvrDialogBase.cpp @@ -66,49 +66,72 @@ IvrDialogBase_dealloc(IvrDialogBase* self) // // Event handlers // -static PyObject* IvrDialogBase_onSessionStart(IvrDialogBase* self, PyObject*) -{ - DBG("no script implementation for onSessionStart(self,hdrs) !!!\n"); +// 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 -} +// PyErr_SetNone(PyExc_NotImplementedError); +// return NULL; // no return value +// } -static PyObject* IvrDialogBase_onBye(IvrDialogBase* self, PyObject*) -{ - DBG("no script implementation for onBye(self) !!!\n"); +// static PyObject* IvrDialogBase_onBye(IvrDialogBase* self, PyObject*) +// { +// DBG("no script implementation for onBye(self) !!!\n"); - PyErr_SetNone(PyExc_NotImplementedError); - return NULL; // no return value -} +// PyErr_SetNone(PyExc_NotImplementedError); +// return NULL; // no return value +// } -static PyObject* IvrDialogBase_onEmptyQueue(IvrDialogBase* self, PyObject*) -{ - DBG("no script implementation for onEmptyQueue(self) !!!\n"); +// static PyObject* IvrDialogBase_onEmptyQueue(IvrDialogBase* self, PyObject*) +// { +// DBG("no script implementation for onEmptyQueue(self) !!!\n"); - PyErr_SetNone(PyExc_NotImplementedError); - return NULL; // no return value -} +// 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; +// 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); +// DBG("IvrDialogBase_onDtmf(%i,%i)\n",key,duration); - Py_INCREF(Py_None); - return Py_None; -} +// Py_INCREF(Py_None); +// return Py_None; +// } -static PyObject* IvrDialogBase_onTimer(IvrDialogBase* self, PyObject* args) -{ - DBG("IvrDialog::onTimer: no script implementation!!!\n"); +// static PyObject* IvrDialogBase_onTimer(IvrDialogBase* self, PyObject* args) +// { +// DBG("IvrDialog::onTimer: no script implementation!!!\n"); - PyErr_SetNone(PyExc_NotImplementedError); - return NULL; // no return value -} +// 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 @@ -366,21 +389,21 @@ IvrDialogBase_getdialog(IvrDialogBase *self, void *closure) static PyMethodDef IvrDialogBase_methods[] = { // Event handlers - {"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" - }, +// {"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, diff --git a/apps/ivr/Makefile b/apps/ivr/Makefile index 2b3077dc..77c4d9a3 100644 --- a/apps/ivr/Makefile +++ b/apps/ivr/Makefile @@ -69,8 +69,7 @@ py_obj = $(py_src:.py=.pyc) ifeq (all,$(MAKECMDGOALS)) .PHONY: python_files python_files: - # python$(PY_VER) py_comp -l -q py &&\ - python$(PY_VER) py_comp -l &&\ + python$(PY_VER) py_comp -l -q py &&\ cp py/*.pyc $(COREPATH)/lib endif