@ -68,6 +68,18 @@
< ref type = " function " > PJSIP_SEND_SESSION_REFRESH < / ref >
< / see - also >
< / function >
< function name = " PJSIP_DTMF_MODE " language = " en_US " >
< synopsis >
Get or change the DTMF mode for a SIP call .
< / synopsis >
< syntax >
< / syntax >
< description >
< para > When read , returns the current DTMF mode < / para >
< para > When written , sets the current DTMF mode < / para >
< para > This function uses the same DTMF mode naming as the dtmf_mode configuration option < / para >
< / description >
< / function >
< function name = " PJSIP_SEND_SESSION_REFRESH " language = " en_US " >
< synopsis >
W / O : Initiate a session refresh via an UPDATE or re - INVITE on an established media session
@ -440,6 +452,7 @@ ASTERISK_REGISTER_FILE()
# include "asterisk/app.h"
# include "asterisk/channel.h"
# include "asterisk/format.h"
# include "asterisk/dsp.h"
# include "asterisk/pbx.h"
# include "asterisk/res_pjsip.h"
# include "asterisk/res_pjsip_session.h"
@ -1039,6 +1052,34 @@ int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char
return ast_sip_push_task_synchronous ( channel - > session - > serializer , media_offer_write_av , & mdata ) ;
}
int pjsip_acf_dtmf_mode_read ( struct ast_channel * chan , const char * cmd , char * data , char * buf , size_t len )
{
struct ast_sip_channel_pvt * channel ;
if ( ! chan ) {
ast_log ( LOG_WARNING , " No channel was provided to %s function. \n " , cmd ) ;
return - 1 ;
}
ast_channel_lock ( chan ) ;
if ( strcmp ( ast_channel_tech ( chan ) - > type , " PJSIP " ) ) {
ast_log ( LOG_WARNING , " Cannot call %s on a non-PJSIP channel \n " , cmd ) ;
ast_channel_unlock ( chan ) ;
return - 1 ;
}
channel = ast_channel_tech_pvt ( chan ) ;
if ( ast_sip_dtmf_to_str ( channel - > session - > dtmf , buf , len ) < 0 ) {
ast_log ( LOG_WARNING , " Unknown DTMF mode %d on PJSIP channel %s \n " , channel - > session - > dtmf , ast_channel_name ( chan ) ) ;
ast_channel_unlock ( chan ) ;
return - 1 ;
}
ast_channel_unlock ( chan ) ;
return 0 ;
}
struct refresh_data {
struct ast_sip_session * session ;
enum ast_sip_session_refresh_method method ;
@ -1067,6 +1108,117 @@ static int sip_session_response_cb(struct ast_sip_session *session, pjsip_rx_dat
return 0 ;
}
static int dtmf_mode_refresh_cb ( void * obj )
{
struct refresh_data * data = obj ;
if ( data - > session - > inv_session - > state = = PJSIP_INV_STATE_CONFIRMED ) {
ast_debug ( 3 , " Changing DTMF mode on channel %s after OFFER/ANSER completion. Sending session refresh \n " , ast_channel_name ( data - > session - > channel ) ) ;
ast_sip_session_refresh ( data - > session , NULL , NULL ,
sip_session_response_cb , data - > method , 1 ) ;
}
return 0 ;
}
int pjsip_acf_dtmf_mode_write ( struct ast_channel * chan , const char * cmd , char * data , const char * value )
{
struct ast_sip_channel_pvt * channel ;
struct chan_pjsip_pvt * pjsip_pvt ;
int dsp_features = 0 ;
int dtmf = - 1 ;
struct refresh_data rdata = {
. method = AST_SIP_SESSION_REFRESH_METHOD_INVITE ,
} ;
if ( ! chan ) {
ast_log ( LOG_WARNING , " No channel was provided to %s function. \n " , cmd ) ;
return - 1 ;
}
ast_channel_lock ( chan ) ;
if ( strcmp ( ast_channel_tech ( chan ) - > type , " PJSIP " ) ) {
ast_log ( LOG_WARNING , " Cannot call %s on a non-PJSIP channel \n " , cmd ) ;
ast_channel_unlock ( chan ) ;
return - 1 ;
}
channel = ast_channel_tech_pvt ( chan ) ;
rdata . session = channel - > session ;
dtmf = ast_sip_str_to_dtmf ( value ) ;
if ( dtmf = = - 1 ) {
ast_log ( LOG_WARNING , " Cannot set DTMF mode to '%s' on channel '%s' as value is invalid. \n " , value ,
ast_channel_name ( chan ) ) ;
ast_channel_unlock ( chan ) ;
return - 1 ;
}
if ( channel - > session - > dtmf = = dtmf ) {
/* DTMF mode unchanged, nothing to do! */
ast_channel_unlock ( chan ) ;
return 0 ;
}
channel - > session - > dtmf = dtmf ;
pjsip_pvt = channel - > pvt ;
if ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] & & ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp ) {
if ( channel - > session - > dtmf = = AST_SIP_DTMF_RFC_4733 ) {
ast_rtp_instance_set_prop ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp , AST_RTP_PROPERTY_DTMF , 1 ) ;
ast_rtp_instance_dtmf_mode_set ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp , AST_RTP_DTMF_MODE_RFC2833 ) ;
} else if ( channel - > session - > dtmf = = AST_SIP_DTMF_INFO ) {
ast_rtp_instance_set_prop ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp , AST_RTP_PROPERTY_DTMF , 0 ) ;
ast_rtp_instance_dtmf_mode_set ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp , AST_RTP_DTMF_MODE_NONE ) ;
} else if ( channel - > session - > dtmf = = AST_SIP_DTMF_INBAND ) {
ast_rtp_instance_set_prop ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp , AST_RTP_PROPERTY_DTMF , 0 ) ;
ast_rtp_instance_dtmf_mode_set ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp , AST_RTP_DTMF_MODE_INBAND ) ;
} else if ( channel - > session - > dtmf = = AST_SIP_DTMF_NONE ) {
ast_rtp_instance_set_prop ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp , AST_RTP_PROPERTY_DTMF , 0 ) ;
ast_rtp_instance_dtmf_mode_set ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp , AST_RTP_DTMF_MODE_NONE ) ;
} else if ( channel - > session - > dtmf = = AST_SIP_DTMF_AUTO ) {
if ( ast_rtp_instance_dtmf_mode_get ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp ) ! = AST_RTP_DTMF_MODE_RFC2833 ) {
/* no RFC4733 negotiated, enable inband */
ast_rtp_instance_dtmf_mode_set ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp , AST_RTP_DTMF_MODE_INBAND ) ;
}
} else if ( channel - > session - > dtmf = = AST_SIP_DTMF_AUTO_INFO ) {
ast_rtp_instance_set_prop ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp , AST_RTP_PROPERTY_DTMF , 0 ) ;
if ( ast_rtp_instance_dtmf_mode_get ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp ) = = AST_RTP_DTMF_MODE_INBAND ) {
/* if inband, switch to INFO */
ast_rtp_instance_dtmf_mode_set ( ( pjsip_pvt - > media [ SIP_MEDIA_AUDIO ] ) - > rtp , AST_RTP_DTMF_MODE_NONE ) ;
}
}
}
if ( channel - > session - > dsp ) {
dsp_features = ast_dsp_get_features ( channel - > session - > dsp ) ;
}
if ( channel - > session - > dtmf = = AST_SIP_DTMF_INBAND | |
channel - > session - > dtmf = = AST_SIP_DTMF_AUTO ) {
dsp_features | = DSP_FEATURE_DIGIT_DETECT ;
} else {
dsp_features & = ~ DSP_FEATURE_DIGIT_DETECT ;
}
if ( dsp_features ) {
if ( ! channel - > session - > dsp ) {
if ( ! ( channel - > session - > dsp = ast_dsp_new ( ) ) ) {
ast_channel_unlock ( chan ) ;
return 0 ;
}
}
ast_dsp_set_features ( channel - > session - > dsp , dsp_features ) ;
} else if ( channel - > session - > dsp ) {
ast_dsp_free ( channel - > session - > dsp ) ;
channel - > session - > dsp = NULL ;
}
ast_channel_unlock ( chan ) ;
return ast_sip_push_task_synchronous ( channel - > session - > serializer , dtmf_mode_refresh_cb , & rdata ) ;
}
static int refresh_write_cb ( void * obj )
{
struct refresh_data * data = obj ;