Hi, I want to use inband dtmf in py_pjysua. I've read about inband dtmf usage in the FAQ, and i've extended the py_pjsua.c with a few new function. Here are my modification, based on PJSIP FAQ: // -- TONE GEN MODIFICATION FOR INBAND DTMF SUPPORT -- struct my_call_data { pj_pool_t *pool; pjmedia_port *tonegen; pjsua_conf_port_id toneslot; }; struct my_call_data *call_init_tonegen(pjsua_call_id call_id) { pj_pool_t *pool; struct my_call_data *cd; pjsua_call_info ci; PJ_LOG(1, (__FILE__, "[D] Initialize tonegen for call_id: %d", call_id ) ); /* pj_pool_t* pjsua_pool_create ( const char * name, pj_size_t init_size, pj_size_t increment ) Create memory pool to be used by the application. Once application finished using the pool, it must be released with pj_pool_release(). Parameters: name Optional pool name. init_size Initial size of the pool. increment Increment size. Returns: The pool, or NULL when there's no memory. Python: Python script may also create a pool object from the script: pool = py_pjsua.pool_create(name, init_size, increment) */ pool = pjsua_pool_create("mycall", 512, 512); cd = PJ_POOL_ZALLOC_T(pool, struct my_call_data); cd->pool = pool; pjmedia_tonegen_create(cd->pool, 8000, 1, 160, 16, 0, &cd->tonegen); pjsua_conf_add_port(cd->pool, cd->tonegen, &cd->toneslot); pjsua_call_get_info(call_id, &ci); pjsua_conf_connect(cd->toneslot, ci.conf_slot); pjsua_call_set_user_data(call_id, (void*) cd); PJ_LOG(1, (__FILE__, "[D] Tone init done" ) ); return cd; } void pjsua_call_inband_dtmf(pjsua_call_id call_id, const pj_str_t *digits) { pjmedia_tone_digit d[16]; unsigned i, count = digits->slen; struct my_call_data *cd; PJ_LOG(1, (__FILE__, "[D] Inband DTMF to call_id: %d; DIGITS: %s", call_id, digits->ptr ) ); cd = (struct my_call_data*) pjsua_call_get_user_data(call_id); if (!cd) { PJ_LOG(1, (__FILE__, "No tonegen found" ) ); cd = call_init_tonegen(call_id); } if (count > PJ_ARRAY_SIZE(d)) count = PJ_ARRAY_SIZE(d); pj_bzero(d, sizeof(d)); for (i=0; i<count; ++i) { d[i].digit = digits->ptr[i]; PJ_LOG(1, (__FILE__, "[D] DIGIT: %c", d[i].digit) ); d[i].on_msec = 100; d[i].off_msec = 200; d[i].volume = 0; } PJ_LOG(1, (__FILE__, "[D] Sending tone; len=%d", count) ); pjmedia_tonegen_play_digits(cd->tonegen, count, d, 0); } void call_deinit_tonegen(pjsua_call_id call_id) { struct my_call_data *cd; PJ_LOG(1, (__FILE__, "[D] Deiniting tonegen.. id: %d", call_id) ); cd = (struct my_call_data*) pjsua_call_get_user_data(call_id); if (!cd) { PJ_LOG(1, (__FILE__, "[D] No tonegen found for id: %d", call_id) ); return; } pjsua_conf_remove_port(cd->toneslot); pjmedia_port_destroy(cd->tonegen); pj_pool_release(cd->pool); pjsua_call_set_user_data(call_id, NULL); PJ_LOG(1, (__FILE__, "[D] Tonegen deinited") ); } /* * py_pjsua_call_inband_dtmf */ static PyObject *py_pjsua_call_inband_dtmf( PyObject *pSelf, PyObject *pArgs ) { int call_id; PyObject * sd; pj_str_t digits; PJ_UNUSED_ARG(pSelf); if (!PyArg_ParseTuple(pArgs, "iO", &call_id, &sd)) { return NULL; } digits.ptr = PyString_AsString(sd); digits.slen = strlen(PyString_AsString(sd)); pjsua_call_inband_dtmf(call_id, &digits); return Py_BuildValue("i", 1); } /* * py_pjsua_deinit_tonegen */ static PyObject *py_pjsua_deinit_tonegen( PyObject *pSelf, PyObject *pArgs ) { int call_id; PJ_UNUSED_ARG(pSelf); if (!PyArg_ParseTuple(pArgs, "i", &call_id)) { return NULL; } call_deinit_tonegen(call_id); return Py_BuildValue("i", 1); } // -- TONE GEN MODIFICATION FOR INBAND DTMF SUPPORT -- .. and I extended the py_pjsua_methods too. { "call_inband_dtmf", py_pjsua_call_inband_dtmf, METH_VARARGS, pjsua_call_inband_dtmf_doc }, { "call_deinit_tonegen", py_pjsua_deinit_tonegen, METH_VARARGS, pjsua_call_deinit_tonegen_doc }, It works fine, I can send inband dtmf using with python, but it works only once. Afther the first 'py_pjsua_call_inband_dtmf' call, I have to deinit the tonegen and reinitialize, and i don't understand why. Ony the first call works: s = raw_input('dtmf#:') while s != 'q': py_pjsua.call_inband_dtmf( call_id, s.strip() ) s = raw_input('dtmf#:') py_pjsua.call_deinit_tonegen( call_id ) This works fine: s = raw_input('dtmf#:') while s != 'q': py_pjsua.call_deinit_tonegen( call_id ) py_pjsua.call_inband_dtmf( call_id, s.strip() ) s = raw_input('dtmf#:') Have you any idea why I have to reinitialize the tonegenerator before each call?