diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml new file mode 100644 index 000000000..010d4b09a --- /dev/null +++ b/.github/workflows/build_test.yml @@ -0,0 +1,29 @@ +name: Build docker images + +on: + push: + branches: + - '**' + +jobs: + images_test_build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Build image based on RHEL7 + run: docker build -t sems -f Dockerfile-rhel7 . + + - name: Build image based on RHEL8 + run: docker build -t sems -f Dockerfile-rhel8 . + + - name: Build image based on RHEL9 + run: docker build -t sems -f Dockerfile-rhel9 . + + - name: Build image based on Debian 11 + run: docker build -t sems -f Dockerfile-debian11 . + + - name: Build image based on Debian 12 + run: docker build -t sems -f Dockerfile-debian12 . diff --git a/.gitignore b/.gitignore index f8d892c9d..555394e74 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ apps/py_sems/sip/*.cpp apps/py_sems/sip/*.h apps/py_sems/sip/Makefile.gen apps/rtmp/flash_phone/*.swf +apps/rtmp/librtmp/librtmp.so.0 apps/xmlrpc2di/xmlrpc++/src/Makefile build/ cmake_install.cmake diff --git a/Dockerfile-debian11 b/Dockerfile-debian11 new file mode 100644 index 000000000..e6daf275f --- /dev/null +++ b/Dockerfile-debian11 @@ -0,0 +1,21 @@ +FROM debian:11 + +RUN apt update +RUN apt install -y \ + git debhelper g++ make libspandsp-dev flite1-dev \ + libspeex-dev libgsm1-dev libopus-dev libssl-dev python3-dev \ + python3.9-dev \ + python3-sip-dev openssl libev-dev libmysqlcppconn-dev libevent-dev \ + libxml2-dev libcurl4-openssl-dev libhiredis-dev + +WORKDIR / + +RUN git clone --depth 1 --branch python3-rhel7 https://github.com/hecko/sems.git + +WORKDIR /sems + +RUN USE_SPANDSP=1 make +RUN USE_SPANDSP=1 make install + +# Run SEMS with the specified configuration +CMD ["/usr/local/sbin/sems", "-E", "-f", "/usr/local/etc/sems/sems.conf"] diff --git a/Dockerfile-debian12 b/Dockerfile-debian12 new file mode 100644 index 000000000..c8df6da9d --- /dev/null +++ b/Dockerfile-debian12 @@ -0,0 +1,21 @@ +FROM debian:12 + +RUN apt update +RUN apt install -y \ + git debhelper g++ make libspandsp-dev flite1-dev \ + libspeex-dev libgsm1-dev libopus-dev libssl-dev python3-dev \ + python3.11-dev \ + python3-sip-dev openssl libev-dev libmysqlcppconn-dev libevent-dev \ + libxml2-dev libcurl4-openssl-dev libhiredis-dev + +WORKDIR / + +RUN git clone --depth 1 --branch python3-rhel7 https://github.com/hecko/sems.git + +WORKDIR /sems + +RUN USE_SPANDSP=1 make +RUN USE_SPANDSP=1 make install + +# Run SEMS with the specified configuration +CMD ["/usr/local/sbin/sems", "-E", "-f", "/usr/local/etc/sems/sems.conf"] diff --git a/Dockerfile-rhel7 b/Dockerfile-rhel7 new file mode 100644 index 000000000..29fbc933a --- /dev/null +++ b/Dockerfile-rhel7 @@ -0,0 +1,42 @@ +FROM centos:7 + +RUN cat /etc/yum.repos.d/CentOS-Base.repo +RUN sed -i '/^mirrorlist=/d; s/^#baseurl=/baseurl=/' /etc/yum.repos.d/*.repo +#RUN find /etc/yum.repos.d/CentOS-*.repo -type f -exec sed -i 's/mirrorlist\.centos\.org/vault\.centos\.org/g' {} + +RUN find /etc/yum.repos.d/CentOS-*.repo -type f -exec sed -i 's/mirror\.centos\.org/vault\.centos\.org/g' {} + +RUN cat /etc/yum.repos.d/CentOS-Base.repo +RUN yum -y update + +RUN yum install -y epel-release \ + && yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm \ + && yum install -y \ + git \ + make \ + gcc-c++ \ + libevent-devel \ + gsm-devel \ + opus-devel \ + speex-devel \ + openssl-devel \ + python3-devel \ + python3.6-devel \ + hiredis-devel \ + zlib-devel \ + libcurl-devel \ + spandsp-devel \ + mysql-connector-c++ \ + python3-mysqlclient --nogpgcheck \ + && ln -s /usr/lib64/libmysqlcppconn8.so.2 /usr/lib64/libmysqlcppconn.so + +WORKDIR / + +RUN git clone --depth 1 --branch python3-rhel7 https://github.com/hecko/sems.git + +WORKDIR /sems + +RUN ln -s /usr/lib64/libpython3.6m.so /usr/lib64/libpython3.6.so +RUN USE_SPANDSP=1 make +RUN USE_SPANDSP=1 make install + +# Run SEMS with the specified configuration +CMD ["/usr/local/sbin/sems", "-E", "-f", "/usr/local/etc/sems/sems.conf"] diff --git a/Dockerfile-rhel8 b/Dockerfile-rhel8 new file mode 100644 index 000000000..2cbbf598a --- /dev/null +++ b/Dockerfile-rhel8 @@ -0,0 +1,37 @@ +FROM almalinux:8 + +RUN yum -y update + +RUN yum install -y epel-release \ + && dnf config-manager --set-enabled powertools \ + && yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm \ + && yum install -y \ + git \ + make \ + gcc-c++ \ + libevent-devel \ + gsm-devel \ + opus-devel \ + speex-devel \ + openssl-devel \ + python36-devel \ + hiredis-devel \ + zlib-devel \ + libcurl-devel \ + spandsp-devel \ + mysql-connector-c++ \ + python3-mysqlclient --nogpgcheck \ + && ln -s /usr/lib64/libmysqlcppconn8.so.2 /usr/lib64/libmysqlcppconn.so + +WORKDIR / + +RUN git clone --depth 1 --branch python3-rhel7 https://github.com/hecko/sems.git + +WORKDIR /sems + +RUN ln -s /usr/lib64/libpython3.6m.so /usr/lib64/libpython3.6.so +RUN USE_SPANDSP=1 make +RUN USE_SPANDSP=1 make install + +# Run SEMS with the specified configuration +CMD ["/usr/local/sbin/sems", "-E", "-f", "/usr/local/etc/sems/sems.conf"] diff --git a/Dockerfile-rhel9 b/Dockerfile-rhel9 new file mode 100644 index 000000000..3dee66035 --- /dev/null +++ b/Dockerfile-rhel9 @@ -0,0 +1,34 @@ +FROM almalinux:9 + +RUN yum install -y epel-release \ + && dnf config-manager --set-enabled crb \ + && dnf install -y https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpm \ + && dnf install -y \ + git \ + make \ + gcc-c++ \ + libevent-devel \ + gsm-devel \ + opus-devel \ + speex-devel \ + openssl-devel \ + python3-devel \ + hiredis-devel \ + zlib-devel \ + libcurl-devel \ + spandsp-devel \ + mysql-connector-c++ \ + python3-mysqlclient --nogpgcheck \ + && ln -s /usr/lib64/libmysqlcppconn8.so.2 /usr/lib64/libmysqlcppconn.so + +WORKDIR / + +RUN git clone --depth 1 --branch python3-rhel7 https://github.com/hecko/sems.git + +WORKDIR /sems + +RUN USE_SPANDSP=1 make +RUN USE_SPANDSP=1 make install + +# Run SEMS with the specified configuration +CMD ["/usr/local/sbin/sems", "-E", "-f", "/usr/local/etc/sems/sems.conf"] diff --git a/README b/README index 7031e66f2..8fa68cb6a 100644 --- a/README +++ b/README @@ -168,8 +168,7 @@ Requirements: All requirements are optional. - o Python version >= 2.3 for the ivr (embedded python interpreter) - and py_sems + o Python for the ivr (embedded python interpreter) and py_sems o flite speech synthesizer for TTS in the ivr o lame >= 3.95 for mp3 file output, mpg123 for mp3 playback o spandsp library for DTMF detection and PLC @@ -177,6 +176,17 @@ Requirements: o libZRTP SDK (http://zfoneproject.com) for ZRTP o libev for jsonrpc +Supported environments: + + SEMS server hes been tested with the following: + * RHEL 7 with Python 3 + * RHEL 8 with Python 3 + * RHEL 9 with Python 3 + * Debian 11 with Python 3 + * Debian 12 with Python 3 + + Please see appropriate Dockerfiles + Creating packages on debian (ubuntu, ...): install debian package build tools: @@ -204,6 +214,13 @@ Creating packages on debian (ubuntu, ...): install sems and sems-python-modules packages in .. using dpkg. +Build and run in container + + # build + docker build -t sems-rhel8 -f Dockerfile-rhel8 + # test-run in foreground + podman run --rm -it --name sems sems-rhel8 + Installed files using 'make install': /usr/local/sbin/sems : SEMS executable diff --git a/apps/Makefile b/apps/Makefile index ac31eb6c1..d99913ab4 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -13,6 +13,8 @@ local_exclude_app_modules += jsonrpc local_exclude_app_modules += mp3 local_exclude_app_modules += py_sems local_exclude_app_modules += twit +# Not supported since RHEL6 or so: +local_exclude_app_modules += ivr-python2 include $(COREPATH)/../Makefile.defs diff --git a/apps/conf_auth/conf_auth.py b/apps/conf_auth/conf_auth.py index 17ee9bd9e..d3ce5b352 100644 --- a/apps/conf_auth/conf_auth.py +++ b/apps/conf_auth/conf_auth.py @@ -1,6 +1,6 @@ from log import * from ivr import * -import xmlrpclib +import xmlrpc XMLRPC_PROTOCOL = 'http' # could e.g. be https @@ -76,7 +76,7 @@ def onDtmf(self,key,duration): self.flush() if key == 10: - c = xmlrpclib.ServerProxy(server_path ) + c = xmlrpc.client.ServerProxy(server_path ) erg = c.AuthorizeConference(self.dialog.remote_uri, self.dialog.local_party, self.keys) diff --git a/apps/dsm/mods/mod_py/Makefile b/apps/dsm/mods/mod_py/Makefile index 7e5d62c1a..bb11108ca 100644 --- a/apps/dsm/mods/mod_py/Makefile +++ b/apps/dsm/mods/mod_py/Makefile @@ -1,6 +1,8 @@ plug_in_name = mod_py -PYTHON_VERSION ?= $(shell python -c 'import sys;print sys.version[0:3]') +PYTHON_VERSION ?= $(shell (python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null) || \ + (python -c 'import sys; assert sys.version_info.major == 3; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null)) + PY_VER = $(PYTHON_VERSION) PY_EXE = python$(PY_VER) @@ -36,4 +38,4 @@ ifneq ($(OS),macosx) ifneq ($(OS),solaris) PYTHON_module_ldflags += -Xlinker --export-dynamic endif -endif \ No newline at end of file +endif diff --git a/apps/dsm/mods/mod_py/ModPy.cpp b/apps/dsm/mods/mod_py/ModPy.cpp index fc888cfd4..8a508e45b 100644 --- a/apps/dsm/mods/mod_py/ModPy.cpp +++ b/apps/dsm/mods/mod_py/ModPy.cpp @@ -36,7 +36,6 @@ #include "AmArg.h" #include -#include "grammar.h" #include "pythread.h" struct PythonGIL @@ -59,20 +58,33 @@ SCPyModule::SCPyModule() { } +#include // For printf and fprintf + int SCPyModule::preload() { - if(!Py_IsInitialized()){ - add_env_path("PYTHONPATH",AmConfig::PlugInPath); + if (!Py_IsInitialized()) { + add_env_path("PYTHONPATH", AmConfig::PlugInPath); Py_Initialize(); - DBG("Python version %s\n", Py_GetVersion()); + printf("Python version %s\n", Py_GetVersion()); } PyEval_InitThreads(); - interp = PyThreadState_Get()->interp; + interp = PyThreadState_Get()->interp; tstate = PyThreadState_Get(); - PyImport_AddModule("dsm"); - dsm_module = Py_InitModule("dsm",mod_py_methods); + static struct PyModuleDef dsm_module_def = { + PyModuleDef_HEAD_INIT, + "dsm", // Module name + NULL, // Optional module documentation + -1, // Module keeps state in global variables + mod_py_methods // Module methods + }; + dsm_module = PyModule_Create(&dsm_module_def); + if (!dsm_module) { + fprintf(stderr, "Failed to create dsm module\n"); + return -1; + } + PyModule_AddIntConstant(dsm_module, "Any", DSMCondition::Any); PyModule_AddIntConstant(dsm_module, "Invite", DSMCondition::Invite); PyModule_AddIntConstant(dsm_module, "SessionStart", DSMCondition::SessionStart); @@ -80,7 +92,7 @@ int SCPyModule::preload() { PyModule_AddIntConstant(dsm_module, "Timer", DSMCondition::Timer); PyModule_AddIntConstant(dsm_module, "NoAudio", DSMCondition::NoAudio); PyModule_AddIntConstant(dsm_module, "Hangup", DSMCondition::Hangup); - PyModule_AddIntConstant(dsm_module, "Hold", DSMCondition::Hold); + PyModule_AddIntConstant(dsm_module, "Hold", DSMCondition::Hold); PyModule_AddIntConstant(dsm_module, "UnHold", DSMCondition::UnHold); PyModule_AddIntConstant(dsm_module, "XmlrpcResponse", DSMCondition::XmlrpcResponse); PyModule_AddIntConstant(dsm_module, "DSMEvent", DSMCondition::DSMEvent); @@ -88,13 +100,24 @@ int SCPyModule::preload() { PyModule_AddIntConstant(dsm_module, "B2BOtherReply", DSMCondition::B2BOtherReply); PyModule_AddIntConstant(dsm_module, "B2BOtherBye", DSMCondition::B2BOtherBye); - PyImport_AddModule("session"); - session_module = Py_InitModule("session",session_methods); + static struct PyModuleDef session_module_def = { + PyModuleDef_HEAD_INIT, + "session", // Module name + NULL, // Optional module documentation + -1, // Module keeps state in global variables + session_methods // Module methods + }; + session_module = PyModule_Create(&session_module_def); + if (!session_module) { + fprintf(stderr, "Failed to create session module\n"); + return -1; + } PyEval_ReleaseLock(); return 0; } + MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) { if (NULL==dsm_module) { @@ -193,23 +216,23 @@ bool py_execute(PyCodeObject* py_func, DSMSession* sc_sess, if (NULL != event_params) { for (map::iterator it=event_params->begin(); it != event_params->end(); it++) { - PyObject* v = PyString_FromString(it->second.c_str()); + PyObject* v = PyUnicode_FromString(it->second.c_str()); PyDict_SetItemString(params, it->first.c_str(), v); Py_DECREF(v); } } PyDict_SetItemString(locals, "params", params); - PyObject *t = PyInt_FromLong(event); + PyObject *t = PyLong_FromLong(event); PyDict_SetItemString(locals, "type", t); - PyObject* py_sc_sess = PyCObject_FromVoidPtr(sc_sess,NULL); + PyObject* py_sc_sess = PyCapsule_New(sc_sess, NULL, NULL); PyObject* ts_dict = PyThreadState_GetDict(); PyDict_SetItemString(ts_dict, "_dsm_sess_", py_sc_sess); Py_DECREF(py_sc_sess); // call the function - PyObject* res = PyEval_EvalCode((PyCodeObject*)py_func, globals, locals); + PyObject* res = PyEval_EvalCode((PyObject*)py_func, globals, locals); if(PyErr_Occurred()) PyErr_Print(); @@ -227,7 +250,7 @@ bool py_execute(PyCodeObject* py_func, DSMSession* sc_sess, if (NULL == res) { ERROR("evaluating python code\n"); } else if (PyBool_Check(res)) { - py_res = PyInt_AsLong(res); + py_res = PyLong_AsLong(res); Py_DECREF(res); } else { if (expect_int_result) { diff --git a/apps/dsm/mods/mod_py/PyDSMSession.cpp b/apps/dsm/mods/mod_py/PyDSMSession.cpp index 172d1dfba..a5f280824 100644 --- a/apps/dsm/mods/mod_py/PyDSMSession.cpp +++ b/apps/dsm/mods/mod_py/PyDSMSession.cpp @@ -41,7 +41,7 @@ extern "C" { return NULL; \ } \ \ - DSMSession* sess = (DSMSession*)PyCObject_AsVoidPtr(py_sc_sess); \ + DSMSession* sess = (DSMSession*)PyCapsule_GetPointer(py_sc_sess, NULL); \ if (NULL == sess) { \ ERROR("retrieving the session pointer from TL dict\n"); \ return NULL; \ @@ -73,7 +73,7 @@ extern "C" { DBG("returning '%s'\n", sess->var[varname].c_str()); - return PyString_FromString(sess->var[varname].c_str()); + return PyUnicode_FromString(sess->var[varname].c_str()); } static PyObject* mod_py_getselect(PyObject*, PyObject* args) @@ -109,7 +109,7 @@ extern "C" { DBG("returning '%s'\n", res.c_str()); - return PyString_FromString(res.c_str()); + return PyUnicode_FromString(res.c_str()); } static PyObject* mod_py_seterror(PyObject*, PyObject* args) @@ -198,7 +198,7 @@ extern "C" { GET_SESS_PTR; unsigned int res = sess->getRecordLength(); DBG("record length %d\n",res); - return PyInt_FromLong(res); + return PyLong_FromLong(res); } static PyObject* getRecordDataSize(PyObject*, PyObject* args) @@ -206,7 +206,7 @@ extern "C" { GET_SESS_PTR; unsigned int res = sess->getRecordDataSize(); DBG("record data size %d\n",res); - return PyInt_FromLong(res); + return PyLong_FromLong(res); } static PyObject* stopRecord(PyObject*, PyObject* args) diff --git a/apps/dsm/mods/mod_py/python_inc.py b/apps/dsm/mods/mod_py/python_inc.py index e2496dde8..bcd417bac 100644 --- a/apps/dsm/mods/mod_py/python_inc.py +++ b/apps/dsm/mods/mod_py/python_inc.py @@ -1,3 +1,3 @@ import distutils.sysconfig -print distutils.sysconfig.get_python_inc(True) +print(distutils.sysconfig.get_python_inc(True)) diff --git a/apps/dsm/mods/mod_py/python_lib.py b/apps/dsm/mods/mod_py/python_lib.py index 9e6425fc3..4103eeb40 100644 --- a/apps/dsm/mods/mod_py/python_lib.py +++ b/apps/dsm/mods/mod_py/python_lib.py @@ -1,3 +1,3 @@ import distutils.sysconfig -print distutils.sysconfig.get_python_lib(True,True) +print(distutils.sysconfig.get_python_lib(True,True)) diff --git a/apps/examples/py_sems_ex/early_media.py b/apps/examples/py_sems_ex/early_media.py index 829150be2..e16a97a6c 100644 --- a/apps/examples/py_sems_ex/early_media.py +++ b/apps/examples/py_sems_ex/early_media.py @@ -17,7 +17,7 @@ def __init__(self): def onInvite(self,req): - print "----------------- %s ----------------" % self.__class__ + print(f"----------------- {self.__class__} ----------------") ann_file = self.getAnnounceFile(req) self.ann = AmAudioFile() @@ -36,18 +36,17 @@ def onInvite(self,req): debug("res = %s" % repr(res)) debug("sdp_reply = %s" % sdp_reply) - if self.dlg.reply(req,183,"OK","application/sdp",sdp_reply,"") <> 0: + if self.dlg.reply(req,183,"OK","application/sdp",sdp_reply,"") != 0: self.setStopped() except: self.dlg.reply(req,500,"File not found","","","") self.ann = None self.setStopped() raise - - - def onSessionStart(self,req): - debug("***** onSessionStart *******") + def onSessionStart(self,req): + + debug("***** onSessionStart *******") PySemsDialog.onSessionStart(self,req) self.localreq = AmSipRequest(req) @@ -84,28 +83,28 @@ def process(self,ev): debug("*********** PySemsScript.process **************") if isinstance(ev,AmAudioEvent): - if ev.event_id == AmAudioEvent.cleared: + if ev.event_id == AmAudioEvent.cleared: - debug("AmAudioEvent.cleared") + debug("AmAudioEvent.cleared") - code = getHeader(self.localreq.hdrs,"P-Final-Reply-Code") - reason = getHeader(self.localreq.hdrs,"P-Final-Reply-Reason") + code = getHeader(self.localreq.hdrs,"P-Final-Reply-Code") + reason = getHeader(self.localreq.hdrs,"P-Final-Reply-Reason") - if reason == "": - reason = "OK" + if reason == "": + reason = "OK" - code_i = 400 - try: - code_i = int(code) - if (code_i < 300) or (code_i>699): - debug("Invalid reply code: %d",code_i) - except: - debug("Invalid reply code: %s",code) - - debug("Replying %d %s" % (code_i, reason)) - self.dlg.reply(self.localreq, code_i, reason, "", "", "") - self.setStopped() - return + code_i = 400 + try: + code_i = int(code) + if (code_i < 300) or (code_i>699): + debug("Invalid reply code: %d",code_i) + except: + debug("Invalid reply code: %s",code) + + debug("Replying %d %s" % (code_i, reason)) + self.dlg.reply(self.localreq, code_i, reason, "", "", "") + self.setStopped() + return PySemsDialog.process(self,ev); return diff --git a/apps/examples/py_sems_ex/jukecall.py b/apps/examples/py_sems_ex/jukecall.py index 3375e4d7d..d2d59e9d5 100644 --- a/apps/examples/py_sems_ex/jukecall.py +++ b/apps/examples/py_sems_ex/jukecall.py @@ -54,7 +54,7 @@ def onInvite(self, req): PySemsB2ABDialog.onInvite(self,req) - def onSessionStart(self,req): + def onSessionStart(self,req): self.setOutput(self.ann) self.initial_user = req.user self.initial_domain = req.domain @@ -82,24 +82,24 @@ def process(self,ev): debug("*********** PySemsScript.process **************") if isinstance(ev,AmAudioEvent): - if ev.event_id == AmAudioEvent.cleared: - debug("AmAudioEvent.cleared") - to = self.initial_user[1:len(self.initial_user)] + \ - "@" + self.initial_domain - debug("to is " + to) - debug("from is "+ self.initial_fromuri) - self.connectCallee("", "sip:"+to, \ - self.initial_fromuri, self.initial_fromuri) - debug("connectcallee ok") - return + if ev.event_id == AmAudioEvent.cleared: + debug("AmAudioEvent.cleared") + to = self.initial_user[1:len(self.initial_user)] + \ + "@" + self.initial_domain + debug("to is " + to) + debug("from is "+ self.initial_fromuri) + self.connectCallee("", "sip:"+to, \ + self.initial_fromuri, self.initial_fromuri) + debug("connectcallee ok") + return PySemsB2ABDialog.process(self,ev); return def createCalleeSession(self): - print self.dlg.local_tag + print(self.dlg.local_tag) cs = MyCalleeSession(self.dlg.local_tag) - print cs + print(cs) return cs def onDtmf(self, event, dur): diff --git a/apps/examples/tutorial/annc_service/annc_service.py b/apps/examples/tutorial/annc_service/annc_service.py index 1b2015676..70978e6dc 100644 --- a/apps/examples/tutorial/annc_service/annc_service.py +++ b/apps/examples/tutorial/annc_service/annc_service.py @@ -9,8 +9,8 @@ from log import * from ivr import * -from urlparse import urlparse, urlsplit -from urllib import urlretrieve +from urllib.parse import urlparse, urlsplit +from urllib.request import urlretrieve from os import unlink TIMEOUT_TIMER_ID = 1 diff --git a/apps/examples/tutorial/cc_acc_xmlrpc/server/xmlrpcserver.py b/apps/examples/tutorial/cc_acc_xmlrpc/server/xmlrpcserver.py index 27218488f..9f540432c 100644 --- a/apps/examples/tutorial/cc_acc_xmlrpc/server/xmlrpcserver.py +++ b/apps/examples/tutorial/cc_acc_xmlrpc/server/xmlrpcserver.py @@ -1,32 +1,34 @@ #!/usr/bin/env python -from SimpleXMLRPCServer import SimpleXMLRPCServer +from xmlrpc.server import SimpleXMLRPCServer import string server = SimpleXMLRPCServer(("localhost", 8000)) server.register_introspection_functions() + class MyFuncs: - def getCredit(self, arg): - print "Function getCredit" - print " Recieved Pin: ", arg - credit=int(arg)+10 - print " Credits: ", credit - return credit + def getCredit(self, arg): + print("Function getCredit") + print(" Recieved Pin: ", arg) + credit = int(arg) + 10 + print(" Credits: ", credit) + return credit + + def subtractCredit(self, arg): + # Since there is no nested values, + # the xml can placed into a standard list + d2 = arg[0] + subtract = d2["amount"] + credit = 1000 - subtract + print("Function subtractCredit ") + print(" Recieved Arg: ", arg[0]) + print(" methodName: ", d2["methodName"]) + print(" pin: ", d2["pin"]) + print(" amount: ", d2["amount"]) + print(" credit: ", credit) + return credit - def subtractCredit(self, arg): - #Since there is no nested values, - # the xml can placed into a standard list - d2 = arg[0] - subtract = d2['amount'] - credit=1000-subtract - print "Function subtractCredit " - print " Recieved Arg: ", arg[0] - print " methodName: ", d2['methodName'] - print " pin: ", d2['pin'] - print " amount: ", d2['amount'] - print " credit: ", credit - return credit server.register_instance(MyFuncs()) server.serve_forever() diff --git a/apps/ivr/Makefile.defs b/apps/ivr/Makefile.defs index e2c49882b..6d7754801 100644 --- a/apps/ivr/Makefile.defs +++ b/apps/ivr/Makefile.defs @@ -1,6 +1,5 @@ -# Python version: 3.x -# -PYTHON_VERSION ?= $(shell python3 -c 'import sys;print("%d.%d" % (sys.version_info.major,sys.version_info.minor))') +PYTHON_VERSION ?= $(shell (python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null) || \ + (python -c 'import sys; assert sys.version_info.major == 3; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null)) PY_VER = $(PYTHON_VERSION) PY_EXE = python$(PY_VER) diff --git a/apps/ivr/Makefile.ivr_application b/apps/ivr/Makefile.ivr_application index 4d00f1ce9..67a69697c 100644 --- a/apps/ivr/Makefile.ivr_application +++ b/apps/ivr/Makefile.ivr_application @@ -36,6 +36,8 @@ clean: .PHONY: compile compile: + echo $(PY_EXE) + echo $(IVRPATH) $(PY_EXE) $(IVRPATH)/py_comp -b -q . .PHONY: install diff --git a/apps/mailbox/mailbox.py b/apps/mailbox/mailbox.py index d4aa00ab5..6fc1a2e09 100644 --- a/apps/mailbox/mailbox.py +++ b/apps/mailbox/mailbox.py @@ -1,5 +1,8 @@ import base64,time +import sys +sys.path.append('/usr/local/lib/sems/ivr/imap_mailbox/') + from log import * from ivr import * diff --git a/apps/pin_collect/Makefile b/apps/pin_collect/Makefile index 62cdbd3ae..942c4cc51 100644 --- a/apps/pin_collect/Makefile +++ b/apps/pin_collect/Makefile @@ -1,5 +1,5 @@ -NAME=pincollect +NAME=pin_collect VERSION=2.3.0-1 LIBDIR=. diff --git a/apps/pin_collect/pin_collect.py b/apps/pin_collect/pin_collect.py index 7afff5af1..28b4dc2b8 100644 --- a/apps/pin_collect/pin_collect.py +++ b/apps/pin_collect/pin_collect.py @@ -1,9 +1,13 @@ # -*- coding: utf-8 -*- + +import sys +sys.path.append('/usr/local/lib/sems/plug-in/') + from log import * from ivr import * if (config['auth_mode'] == 'XMLRPC'): - import xmlrpclib + import xmlrpc #states collect = 0 @@ -35,19 +39,19 @@ def sessionInfo(self): debug("IVR Session info:") debug(" user: " + self.dialog.user) debug(" domain: " + self.dialog.domain) - debug(" sip_ip: " + self.dialog.sip_ip) - debug(" sip_port: " + self.dialog.sip_port) - debug(" local_uri: " + self.dialog.local_uri) - debug(" remote_uri: " + self.dialog.remote_uri) - debug(" contact_uri: " + self.dialog.contact_uri) - debug(" callid: " + self.dialog.callid) - debug(" remote_tag: " + self.dialog.remote_tag) - debug(" local_tag: " + self.dialog.local_tag) - debug(" remote_party:" + self.dialog.remote_party) - debug(" local_party: " + self.dialog.local_party) - debug(" route: " + self.dialog.route) - debug(" next_hop: " + self.dialog.next_hop) - debug(" cseq: " + str(self.dialog.cseq)) + # debug(" sip_ip: " + self.dialog.sip_ip) + # debug(" sip_port: " + self.dialog.sip_port) + # debug(" local_uri: " + self.dialog.local_uri) + # debug(" remote_uri: " + self.dialog.remote_uri) + # debug(" contact_uri: " + self.dialog.contact_uri) + # debug(" callid: " + self.dialog.callid) + # debug(" remote_tag: " + self.dialog.remote_tag) + # debug(" local_tag: " + self.dialog.local_tag) + # debug(" remote_party:" + self.dialog.remote_party) + # debug(" local_party: " + self.dialog.local_party) + # debug(" route: " + self.dialog.route) + # debug(" next_hop: " + self.dialog.next_hop) + # debug(" cseq: " + str(self.dialog.cseq)) def onSessionStart(self): self.sessionInfo() @@ -76,7 +80,7 @@ def onDtmf(self,key,duration): # XMLRPC authentication mode if (config['auth_mode'] == 'XMLRPC'): try: - c = xmlrpclib.ServerProxy(config['auth_xmlrpc_url']) + c = xmlrpc.client.ServerProxy(config['auth_xmlrpc_url']) erg = c.authorize(self.dialog.user, self.keys) debug('result of authentication: '+ str(erg)) diff --git a/apps/py_sems/Makefile.defs b/apps/py_sems/Makefile.defs index 3546d78c7..54d639e34 100644 --- a/apps/py_sems/Makefile.defs +++ b/apps/py_sems/Makefile.defs @@ -1,6 +1,5 @@ -# PYTHON_VERSION might also be 2.2 -- except for the use of GIL -# do a ls /usr/include/python2.3/Python.h to see if it's there -PYTHON_VERSION ?= `python -c 'import sys;print sys.version[0:3]';` +PYTHON_VERSION ?= $(shell (python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null) || \ + (python -c 'import sys; assert sys.version_info.major == 3; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null)) PY_VER = $(PYTHON_VERSION) PY_EXE = python$(PY_VER) diff --git a/apps/py_sems/Makefile.py_sems_application b/apps/py_sems/Makefile.py_sems_application index 02a17cf8c..bfb4cd66e 100644 --- a/apps/py_sems/Makefile.py_sems_application +++ b/apps/py_sems/Makefile.py_sems_application @@ -31,7 +31,7 @@ clean: .PHONY: compile compile: - python${PYTHON_VERSION} $(PYSEMSPATH)/py_comp -q . + python${PYTHON_VERSION} $(PYSEMSPATH)/py_comp -b -q . .PHONY: install install: all diff --git a/apps/py_sems/py/py_sems_log.py b/apps/py_sems/py/py_sems_log.py index cd648ed7b..16c1d3f42 100644 --- a/apps/py_sems/py/py_sems_log.py +++ b/apps/py_sems/py/py_sems_log.py @@ -2,56 +2,61 @@ import sys # These are the same as in log.h -L_ERR = 0 +L_ERR = 0 L_WARN = 1 L_INFO = 2 -L_DBG = 3 +L_DBG = 3 + def log(level, msg, args): - if args != None: - tmp_msg = msg % args - else: - tmp_msg = msg - - py_sems.log(level,"PySems: " + tmp_msg + "\n") + if args != None: + tmp_msg = msg % args + else: + tmp_msg = msg + + py_sems.log(level, "PySems: " + tmp_msg + "\n") def error(msg, args=None): - log(L_ERR, msg, args) + log(L_ERR, msg, args) + def warn(msg, args=None): - log(L_WARN, msg, args) + log(L_WARN, msg, args) + def info(msg, args=None): - log(L_INFO, msg, args) - + log(L_INFO, msg, args) + + def debug(msg, args=None): - log(L_DBG, msg, args) + log(L_DBG, msg, args) def stacktrace(tb): - if tb: last_file = stacktrace(tb.tb_next) - else: return + if tb: + last_file = stacktrace(tb.tb_next) + else: + return - f = tb.tb_frame.f_code.co_filename - line = tb.tb_frame.f_lineno + f = tb.tb_frame.f_code.co_filename + line = tb.tb_frame.f_lineno - if f != last_file: - error('File ' + `f` + ': line ' + `line`) - else: - error(', line ' + `line`) - return f + if f != last_file: + error("File " + repr(f) + ": line " + repr(line)) + else: + error(", line " + repr(line)) + return f def log_excepthook(exception, value, tb): - error('********** PySems exception report ****************') - error(str(exception) + ' raised: ' + str(value)) - stacktrace(tb) - error('********** end of PySems exception report *********') - + error("********** PySems exception report ****************") + error(str(exception) + " raised: " + str(value)) + stacktrace(tb) + error("********** end of PySems exception report *********") # init code diff --git a/apps/py_sems/python_inc.py b/apps/py_sems/python_inc.py index e2496dde8..bcd417bac 100644 --- a/apps/py_sems/python_inc.py +++ b/apps/py_sems/python_inc.py @@ -1,3 +1,3 @@ import distutils.sysconfig -print distutils.sysconfig.get_python_inc(True) +print(distutils.sysconfig.get_python_inc(True)) diff --git a/apps/py_sems/python_lib.py b/apps/py_sems/python_lib.py index 9e6425fc3..9008e4915 100644 --- a/apps/py_sems/python_lib.py +++ b/apps/py_sems/python_lib.py @@ -1,3 +1,3 @@ import distutils.sysconfig -print distutils.sysconfig.get_python_lib(True,True) +print(distutils.sysconfig.get_python_lib(True, True)) diff --git a/apps/sbc/call_control/prepaid_xmlrpc/server/xmlrpcserver.py b/apps/sbc/call_control/prepaid_xmlrpc/server/xmlrpcserver.py index 27218488f..9f540432c 100644 --- a/apps/sbc/call_control/prepaid_xmlrpc/server/xmlrpcserver.py +++ b/apps/sbc/call_control/prepaid_xmlrpc/server/xmlrpcserver.py @@ -1,32 +1,34 @@ #!/usr/bin/env python -from SimpleXMLRPCServer import SimpleXMLRPCServer +from xmlrpc.server import SimpleXMLRPCServer import string server = SimpleXMLRPCServer(("localhost", 8000)) server.register_introspection_functions() + class MyFuncs: - def getCredit(self, arg): - print "Function getCredit" - print " Recieved Pin: ", arg - credit=int(arg)+10 - print " Credits: ", credit - return credit + def getCredit(self, arg): + print("Function getCredit") + print(" Recieved Pin: ", arg) + credit = int(arg) + 10 + print(" Credits: ", credit) + return credit + + def subtractCredit(self, arg): + # Since there is no nested values, + # the xml can placed into a standard list + d2 = arg[0] + subtract = d2["amount"] + credit = 1000 - subtract + print("Function subtractCredit ") + print(" Recieved Arg: ", arg[0]) + print(" methodName: ", d2["methodName"]) + print(" pin: ", d2["pin"]) + print(" amount: ", d2["amount"]) + print(" credit: ", credit) + return credit - def subtractCredit(self, arg): - #Since there is no nested values, - # the xml can placed into a standard list - d2 = arg[0] - subtract = d2['amount'] - credit=1000-subtract - print "Function subtractCredit " - print " Recieved Arg: ", arg[0] - print " methodName: ", d2['methodName'] - print " pin: ", d2['pin'] - print " amount: ", d2['amount'] - print " credit: ", credit - return credit server.register_instance(MyFuncs()) server.serve_forever() diff --git a/apps/webconference/pyqtgui/webconference.py b/apps/webconference/pyqtgui/webconference.py index 402841fc3..0f09eb4bc 100755 --- a/apps/webconference/pyqtgui/webconference.py +++ b/apps/webconference/pyqtgui/webconference.py @@ -15,192 +15,246 @@ from PyQt4.QtGui import * from PyQt4.QtCore import * -from xmlrpclib import * +from xmlrpc.client import * from threading import * -from conftable import * +from conftable import * from participant import * from callbox import * from account import * # URI for XMLRPC webconference control, set to your server, e.g. for local host: -#CONTROL_URI="http://127.0.0.1:8090/" -CONTROL_URI="https://webconference.iptel.org/control" +# CONTROL_URI="http://127.0.0.1:8090/" +CONTROL_URI = "https://webconference.iptel.org/control" -print "Server Control URI: '%s' - change CONTROL_URI to use local SEMS instance" % CONTROL_URI +print( + "Server Control URI: '%s' - change CONTROL_URI to use local SEMS instance" + % CONTROL_URI +) # refresh in ms -REFRESH_INTERVAL=1000 +REFRESH_INTERVAL = 1000 -HAS_ACCOUNT=False +HAS_ACCOUNT = False try: - from accountconfig import * - HAS_ACCOUNT=True + from accountconfig import * + + HAS_ACCOUNT = True except: - print "accountconfig.py not found - will ask for account to make calls" - pass + print("accountconfig.py not found - will ask for account to make calls") + pass + class named_participant(Ui_participant): - def __init__(self, parent, title, callid, id): - self.callid = callid - self.id = id - self.setupUi(parent) - self.parent = parent - self.tag = "" - parent.setWindowTitle(title) - QtCore.QObject.connect(self.bt_ciao, QtCore.SIGNAL("clicked()"), self.ciao_clicked) - QtCore.QObject.connect(self.cb_muted, QtCore.SIGNAL("stateChanged(int)"), self.muted_changed) - - def ciao_clicked(self): - self.bt_ciao.emit(QtCore.SIGNAL("ciao(int)"), self.id) - - def status2text(self, s): - return { 0: "Disconnected", - 1: "Connecting", - 2: "Ringing", - 3: "Connected", - 4: "Disconnecting", - 5: "Finished"}[s] - - def set_status(self, status, hint, muted): - self.l_status.setText(self.status2text(status)) - self.l_status.setToolTip(hint) - if muted: - self.cb_muted.setCheckState(Qt.Checked) - else: - self.cb_muted.setCheckState(Qt.Unchecked) - - def muted_changed(self, i): - print "callid is" , self.callid - self.cb_muted.emit(QtCore.SIGNAL("mute(int,bool)"), self.id, self.cb_muted.isChecked()) - - + def __init__(self, parent, title, callid, id): + self.callid = callid + self.id = id + self.setupUi(parent) + self.parent = parent + self.tag = "" + parent.setWindowTitle(title) + QtCore.QObject.connect( + self.bt_ciao, QtCore.SIGNAL("clicked()"), self.ciao_clicked + ) + QtCore.QObject.connect( + self.cb_muted, QtCore.SIGNAL("stateChanged(int)"), self.muted_changed + ) + + def ciao_clicked(self): + self.bt_ciao.emit(QtCore.SIGNAL("ciao(int)"), self.id) + + def status2text(self, s): + return { + 0: "Disconnected", + 1: "Connecting", + 2: "Ringing", + 3: "Connected", + 4: "Disconnecting", + 5: "Finished", + }[s] + + def set_status(self, status, hint, muted): + self.l_status.setText(self.status2text(status)) + self.l_status.setToolTip(hint) + if muted: + self.cb_muted.setCheckState(Qt.Checked) + else: + self.cb_muted.setCheckState(Qt.Unchecked) + + def muted_changed(self, i): + print("callid is", self.callid) + self.cb_muted.emit( + QtCore.SIGNAL("mute(int,bool)"), self.id, self.cb_muted.isChecked() + ) + + class StartQT4(QtGui.QMainWindow): - participants = [] - roomname = "" - adminpin = "" - s = None - last_res = None - - def __init__(self, parent=None): - QtGui.QWidget.__init__(self, parent) - self.ui = Ui_MainWindow() - self.ui.setupUi(self) - self.show() - - if HAS_ACCOUNT: - self.call_domain = DOMAIN - self.call_user = USER - self.call_pwd = PASSWORD - self.call_auth_user = AUTH_USER - else: - dlg = QtGui.QDialog(self) - dlg_cb = Ui_account() - dlg_cb.setupUi(dlg) - if dlg.exec_() == QDialog.Rejected: - raise "well, I need a SIP account to make calls" - - self.call_domain = str(dlg_cb.e_domain.text()) - self.call_pwd = str(dlg_cb.e_pwd.text()) - self.call_user = str(dlg_cb.e_user.text()) - self.call_auth_user = self.call_user - - QtCore.QObject.connect(self.ui.buttonNew, QtCore.SIGNAL("clicked()"), self.new_call) - self.s = ServerProxy(CONTROL_URI) - print "server has %d running calls " % self.s.calls() - for i in range(10): - self.roomname = "" - for n in range(6): - self.roomname+=str(random.randint(0,9)) - code, result, adminpin, serverstatus = self.s.di('webconference', 'roomCreate', self.roomname) - print "server status: %s " % serverstatus - if code == 0: - self.adminpin = adminpin - break - if self.adminpin == "": - raise "oh, could not get a free room :(" - - print "roomname is %s, adminpin is %s "% (self.roomname, self.adminpin) - self.ui.label.setText("iptel.org\nwebconference\nhttps://webconference.iptel.org\n\nroom: %s adminpin:%s\n\n" - "to dial in call sip:conference@iptel.org \nand type %s*" - %(self.roomname, self.adminpin, self.roomname)) - - self.timer = QtCore.QTimer(self) - self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.timer_hit) - self.timer.start(REFRESH_INTERVAL) - - def timer_hit(self): - res = self.s.di('webconference', 'roomInfo', self.roomname, self.adminpin) - if res[0] != 0: - print "oh my god, can't see this room!" - return - - code, reason, participants, serverstatus = res - if participants == self.last_res: - return #optimize a bit - - self.last_res = participants - - for part in participants: - call_tag, number, status, reason, muted, participant_id = part - found = False - for p in self.participants: - if p.callid == call_tag: - p.set_status(status, reason, muted) - found = True - break - if not found: - p = self.createparticipantWidget(number, call_tag) - p.set_status(status, reason, muted) - - def createparticipantWidget(self, name, callid): - w = QtGui.QDockWidget("someone", self.ui.frame_main) - part = named_participant(w, name, callid, len(self.participants)) - QtCore.QObject.connect(part.bt_ciao, QtCore.SIGNAL("ciao(int)"), self.part_ciao) - QtCore.QObject.connect(part.cb_muted, QtCore.SIGNAL("mute(int,bool)"), self.part_muted) - self.addDockWidget(random.choice([QtCore.Qt.RightDockWidgetArea, QtCore.Qt.LeftDockWidgetArea, QtCore.Qt.TopDockWidgetArea]), w) - w.setFloating(True) - w.show() - self.participants = self.participants + [ part ] - return part - - def new_call(self): - print "a new call." - dlg = QtGui.QDialog(self) - dlg_cb = Ui_callbox() - dlg_cb.setupUi(dlg) - if dlg.exec_() == QDialog.Rejected: - return - - print "now calling %s " % dlg_cb.num.text() - res = self.s.di('webconference', 'dialout', self.roomname, self.adminpin, str(dlg_cb.num.text()), - self.call_user, self.call_domain, self.call_auth_user, self.call_pwd) - if res[0] != 0: - print "oh, my dear, calling failed with code %d " % res[0] - return - code, result, callid, serverinfo = res - print "code %d result %s " % (code, result) - print "serverinfo is %s " % serverinfo - - self.createparticipantWidget(dlg_cb.num.text(), callid) - - def part_ciao(self, id): - print "ciao: ", id - self.s.di('webconference', 'kickout', self.roomname, self.adminpin, self.participants[id].callid) - - def part_muted(self, id, s): - print "mute: ", id, " is ", s - if s: - self.s.di('webconference', 'mute', self.roomname, self.adminpin, self.participants[id].callid) - else: - self.s.di('webconference', 'unmute', self.roomname, self.adminpin, self.participants[id].callid) - - + participants = [] + roomname = "" + adminpin = "" + s = None + last_res = None + def __init__(self, parent=None): + QtGui.QWidget.__init__(self, parent) + self.ui = Ui_MainWindow() + self.ui.setupUi(self) + self.show() -if __name__ == "__main__": - app = QtGui.QApplication(sys.argv) - myapp = StartQT4() - myapp.show() - sys.exit(app.exec_()) + if HAS_ACCOUNT: + self.call_domain = DOMAIN + self.call_user = USER + self.call_pwd = PASSWORD + self.call_auth_user = AUTH_USER + else: + dlg = QtGui.QDialog(self) + dlg_cb = Ui_account() + dlg_cb.setupUi(dlg) + if dlg.exec_() == QDialog.Rejected: + raise Exception("well, I need a SIP account to make calls") + + self.call_domain = str(dlg_cb.e_domain.text()) + self.call_pwd = str(dlg_cb.e_pwd.text()) + self.call_user = str(dlg_cb.e_user.text()) + self.call_auth_user = self.call_user + + QtCore.QObject.connect( + self.ui.buttonNew, QtCore.SIGNAL("clicked()"), self.new_call + ) + self.s = ServerProxy(CONTROL_URI) + print("server has %d running calls " % self.s.calls()) + for i in range(10): + self.roomname = "" + for n in range(6): + self.roomname += str(random.randint(0, 9)) + code, result, adminpin, serverstatus = self.s.di( + "webconference", "roomCreate", self.roomname + ) + print("server status: %s " % serverstatus) + if code == 0: + self.adminpin = adminpin + break + if self.adminpin == "": + raise Exception("oh, could not get a free room :(") + + print("roomname is %s, adminpin is %s " % (self.roomname, self.adminpin)) + self.ui.label.setText( + "iptel.org\nwebconference\nhttps://webconference.iptel.org\n\nroom: %s adminpin:%s\n\n" + "to dial in call sip:conference@iptel.org \nand type %s*" + % (self.roomname, self.adminpin, self.roomname) + ) + + self.timer = QtCore.QTimer(self) + self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.timer_hit) + self.timer.start(REFRESH_INTERVAL) + def timer_hit(self): + res = self.s.di("webconference", "roomInfo", self.roomname, self.adminpin) + if res[0] != 0: + print("oh my god, can't see this room!") + return + + code, reason, participants, serverstatus = res + if participants == self.last_res: + return # optimize a bit + + self.last_res = participants + + for part in participants: + call_tag, number, status, reason, muted, participant_id = part + found = False + for p in self.participants: + if p.callid == call_tag: + p.set_status(status, reason, muted) + found = True + break + if not found: + p = self.createparticipantWidget(number, call_tag) + p.set_status(status, reason, muted) + + def createparticipantWidget(self, name, callid): + w = QtGui.QDockWidget("someone", self.ui.frame_main) + part = named_participant(w, name, callid, len(self.participants)) + QtCore.QObject.connect(part.bt_ciao, QtCore.SIGNAL("ciao(int)"), self.part_ciao) + QtCore.QObject.connect( + part.cb_muted, QtCore.SIGNAL("mute(int,bool)"), self.part_muted + ) + self.addDockWidget( + random.choice( + [ + QtCore.Qt.RightDockWidgetArea, + QtCore.Qt.LeftDockWidgetArea, + QtCore.Qt.TopDockWidgetArea, + ] + ), + w, + ) + w.setFloating(True) + w.show() + self.participants = self.participants + [part] + return part + + def new_call(self): + print("a new call.") + dlg = QtGui.QDialog(self) + dlg_cb = Ui_callbox() + dlg_cb.setupUi(dlg) + if dlg.exec_() == QDialog.Rejected: + return + + print("now calling %s " % dlg_cb.num.text()) + res = self.s.di( + "webconference", + "dialout", + self.roomname, + self.adminpin, + str(dlg_cb.num.text()), + self.call_user, + self.call_domain, + self.call_auth_user, + self.call_pwd, + ) + if res[0] != 0: + print("oh, my dear, calling failed with code %d " % res[0]) + return + code, result, callid, serverinfo = res + print("code %d result %s " % (code, result)) + print("serverinfo is %s " % serverinfo) + + self.createparticipantWidget(dlg_cb.num.text(), callid) + + def part_ciao(self, id): + print("ciao: ", id) + self.s.di( + "webconference", + "kickout", + self.roomname, + self.adminpin, + self.participants[id].callid, + ) + + def part_muted(self, id, s): + print("mute: ", id, " is ", s) + if s: + self.s.di( + "webconference", + "mute", + self.roomname, + self.adminpin, + self.participants[id].callid, + ) + else: + self.s.di( + "webconference", + "unmute", + self.roomname, + self.adminpin, + self.participants[id].callid, + ) + + +if __name__ == "__main__": + app = QtGui.QApplication(sys.argv) + myapp = StartQT4() + myapp.show() + sys.exit(app.exec_()) diff --git a/apps/webconference/tools/sems-webconference-addparticipant b/apps/webconference/tools/sems-webconference-addparticipant index 63ca8d8b0..e031b1800 100755 --- a/apps/webconference/tools/sems-webconference-addparticipant +++ b/apps/webconference/tools/sems-webconference-addparticipant @@ -1,12 +1,12 @@ #!/usr/bin/python # -*- coding: utf-8 -*- import sys -from xmlrpclib import * +from xmlrpc.client import * if len(sys.argv) != 4: - print "usage: %s " % sys.argv[0] - sys.exit(1) + print("usage: %s " % sys.argv[0]) + sys.exit(1) -s = ServerProxy('http://localhost:8090') -print "Active calls: %d" % s.calls() -print s.di('webconference','addParticipant', sys.argv[1], sys.argv[2], sys.argv[3]) +s = ServerProxy("http://localhost:8090") +print("Active calls: %d" % s.calls()) +print(s.di("webconference", "addParticipant", sys.argv[1], sys.argv[2], sys.argv[3])) diff --git a/apps/webconference/tools/sems-webconference-roomcreate b/apps/webconference/tools/sems-webconference-roomcreate index 55682642f..e57269cae 100755 --- a/apps/webconference/tools/sems-webconference-roomcreate +++ b/apps/webconference/tools/sems-webconference-roomcreate @@ -1,12 +1,12 @@ #!/usr/bin/python # -*- coding: utf-8 -*- import sys -from xmlrpclib import * +from xmlrpc.client import * if len(sys.argv) != 2: - print "usage: %s " % sys.argv[0] - sys.exit(1) + print("usage: %s " % sys.argv[0]) + sys.exit(1) -s = ServerProxy('http://localhost:8090') -print "Active calls: %d" % s.calls() -print s.di('webconference','roomCreate', sys.argv[1]) +s = ServerProxy("http://localhost:8090") +print("Active calls: %d" % s.calls()) +print(s.di("webconference", "roomCreate", sys.argv[1])) diff --git a/apps/webconference/tools/sems-webconference-roominfo b/apps/webconference/tools/sems-webconference-roominfo index 074140b32..a4357d347 100755 --- a/apps/webconference/tools/sems-webconference-roominfo +++ b/apps/webconference/tools/sems-webconference-roominfo @@ -1,12 +1,12 @@ #!/usr/bin/python # -*- coding: utf-8 -*- import sys -from xmlrpclib import * +from xmlrpc.client import * if len(sys.argv) != 3: - print "usage: %s " % sys.argv[0] - sys.exit(1) + print("usage: %s " % sys.argv[0]) + sys.exit(1) -s = ServerProxy('http://localhost:8090') -print "Active calls: %d" % s.calls() -print s.di('webconference','roomInfo', sys.argv[1], sys.argv[2]) +s = ServerProxy("http://localhost:8090") +print("Active calls: %d" % s.calls()) +print(s.di("webconference", "roomInfo", sys.argv[1], sys.argv[2])) diff --git a/doc/Readme.ivr.txt b/doc/Readme.ivr.txt index f3a89906a..8564bddcd 100644 --- a/doc/Readme.ivr.txt +++ b/doc/Readme.ivr.txt @@ -28,11 +28,9 @@ For security reasons, only pre-loaded scripts can be executed. How to select which Python script will be executed: --------------------------------------------------- -If the application determined by the normal application selection -(sems.conf application=xyz) is "ivr", the script is executed which -is named as the username. -Example: R-URI 123@sems.iptel.org starts /123.py - +Depending on the sems.conf file this is the way how Python scrips gets selected: + application = $(ruri.user) + When R-URI is 123@sems.iptel.org, then /123.py starts Troubleshooting: ----------------