[asterisk-commits] russell: branch group/vldtmf_fixup r51200 - in /team/group/vldtmf_fixup: chan...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed Jan 17 14:28:35 MST 2007


Author: russell
Date: Wed Jan 17 15:28:34 2007
New Revision: 51200

URL: http://svn.digium.com/view/asterisk?view=rev&rev=51200
Log:
Fix various issues related to VLDTMF.

- The send_digit_end callback now accepts a duration.  This allows us to send
  the real digit duration in a SIP INFO message, as opposed to a hard coded
  250 ms.

- When a SIP channel is using INFO for DTMF, make the core know that it doesn't
  care about DTMF begin frames.

- Only allow direct media bridging of RTP if the DTMF modes match.

Modified:
    team/group/vldtmf_fixup/channels/chan_agent.c
    team/group/vldtmf_fixup/channels/chan_alsa.c
    team/group/vldtmf_fixup/channels/chan_features.c
    team/group/vldtmf_fixup/channels/chan_gtalk.c
    team/group/vldtmf_fixup/channels/chan_h323.c
    team/group/vldtmf_fixup/channels/chan_iax2.c
    team/group/vldtmf_fixup/channels/chan_local.c
    team/group/vldtmf_fixup/channels/chan_mgcp.c
    team/group/vldtmf_fixup/channels/chan_misdn.c
    team/group/vldtmf_fixup/channels/chan_oss.c
    team/group/vldtmf_fixup/channels/chan_phone.c
    team/group/vldtmf_fixup/channels/chan_sip.c
    team/group/vldtmf_fixup/channels/chan_skinny.c
    team/group/vldtmf_fixup/channels/chan_zap.c
    team/group/vldtmf_fixup/include/asterisk/channel.h
    team/group/vldtmf_fixup/include/asterisk/frame.h
    team/group/vldtmf_fixup/main/channel.c
    team/group/vldtmf_fixup/main/rtp.c

Modified: team/group/vldtmf_fixup/channels/chan_agent.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_agent.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_agent.c (original)
+++ team/group/vldtmf_fixup/channels/chan_agent.c Wed Jan 17 15:28:34 2007
@@ -238,7 +238,7 @@
 static int agent_devicestate(void *data);
 static void agent_logoff_maintenance(struct agent_pvt *p, char *loginchan, long logintime, const char *uniqueid, char *logcommand);
 static int agent_digit_begin(struct ast_channel *ast, char digit);
-static int agent_digit_end(struct ast_channel *ast, char digit);
+static int agent_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int agent_call(struct ast_channel *ast, char *dest, int timeout);
 static int agent_hangup(struct ast_channel *ast);
 static int agent_answer(struct ast_channel *ast);
@@ -617,12 +617,12 @@
 	return res;
 }
 
-static int agent_digit_end(struct ast_channel *ast, char digit)
+static int agent_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct agent_pvt *p = ast->tech_pvt;
 	int res = -1;
 	ast_mutex_lock(&p->lock);
-	ast_senddigit_end(p->chan, digit);
+	ast_senddigit_end(p->chan, digit, duration);
 	ast_mutex_unlock(&p->lock);
 	return res;
 }

Modified: team/group/vldtmf_fixup/channels/chan_alsa.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_alsa.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_alsa.c (original)
+++ team/group/vldtmf_fixup/channels/chan_alsa.c Wed Jan 17 15:28:34 2007
@@ -187,7 +187,7 @@
 
 /* ZZ */
 static struct ast_channel *alsa_request(const char *type, int format, void *data, int *cause);
-static int alsa_digit(struct ast_channel *c, char digit);
+static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration);
 static int alsa_text(struct ast_channel *c, const char *text);
 static int alsa_hangup(struct ast_channel *c);
 static int alsa_answer(struct ast_channel *c);
@@ -487,10 +487,11 @@
 	return readdev;
 }
 
-static int alsa_digit(struct ast_channel *c, char digit)
-{
-	ast_mutex_lock(&alsalock);
-	ast_verbose(" << Console Received digit %c >> \n", digit);
+static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration)
+{
+	ast_mutex_lock(&alsalock);
+	ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 
+		digit, duration);
 	ast_mutex_unlock(&alsalock);
 	return 0;
 }

Modified: team/group/vldtmf_fixup/channels/chan_features.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_features.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_features.c (original)
+++ team/group/vldtmf_fixup/channels/chan_features.c Wed Jan 17 15:28:34 2007
@@ -96,7 +96,7 @@
 
 static struct ast_channel *features_request(const char *type, int format, void *data, int *cause);
 static int features_digit_begin(struct ast_channel *ast, char digit);
-static int features_digit_end(struct ast_channel *ast, char digit);
+static int features_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int features_call(struct ast_channel *ast, char *dest, int timeout);
 static int features_hangup(struct ast_channel *ast);
 static int features_answer(struct ast_channel *ast);
@@ -318,7 +318,7 @@
 	return res;
 }
 
-static int features_digit_end(struct ast_channel *ast, char digit)
+static int features_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct feature_pvt *p = ast->tech_pvt;
 	int res = -1;
@@ -328,7 +328,7 @@
 	ast_mutex_lock(&p->lock);
 	x = indexof(p, ast, 0);
 	if (!x && p->subchan)
-		res = ast_senddigit_end(p->subchan, digit);
+		res = ast_senddigit_end(p->subchan, digit, duration);
 	ast_mutex_unlock(&p->lock);
 	return res;
 }

Modified: team/group/vldtmf_fixup/channels/chan_gtalk.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_gtalk.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_gtalk.c (original)
+++ team/group/vldtmf_fixup/channels/chan_gtalk.c Wed Jan 17 15:28:34 2007
@@ -173,7 +173,9 @@
 
 /* Forward declarations */
 static struct ast_channel *gtalk_request(const char *type, int format, void *data, int *cause);
-static int gtalk_digit(struct ast_channel *ast, char digit);
+static int gtalk_digit(struct ast_channel *ast, char digit, unsigned int duration);
+static int gtalk_digit_begin(struct ast_channel *ast, char digit);
+static int gtalk_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int gtalk_call(struct ast_channel *ast, char *dest, int timeout);
 static int gtalk_hangup(struct ast_channel *ast);
 static int gtalk_answer(struct ast_channel *ast);
@@ -198,8 +200,8 @@
 	.description = "Gtalk Channel Driver",
 	.capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
 	.requester = gtalk_request,
-	.send_digit_begin = gtalk_digit,
-	.send_digit_end = gtalk_digit,
+	.send_digit_begin = gtalk_digit_begin,
+	.send_digit_end = gtalk_digit_end,
 	.bridge = ast_rtp_bridge,
 	.call = gtalk_call,
 	.hangup = gtalk_hangup,
@@ -1341,7 +1343,17 @@
 	return res;
 }
 
-static int gtalk_digit(struct ast_channel *ast, char digit)
+static int gtalk_digit_begin(struct ast_channel *chan, char digit)
+{
+	return gtalk_digit(chan, digit, 0);
+}
+
+static int gtalk_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
+{
+	return gtalk_digit(chan, digit, duration);
+}
+
+static int gtalk_digit(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct gtalk_pvt *p = ast->tech_pvt;
 	struct gtalk *client = p->parent;
@@ -1376,8 +1388,8 @@
 	iks_insert_node(gtalk, dtmf);
 
 	ast_mutex_lock(&p->lock);
-	if(ast->dtmff.frametype == AST_FRAME_DTMF) {
-		ast_verbose("Sending 250ms dtmf!\n");
+	if (ast->dtmff.frametype == AST_FRAME_DTMF) {
+		ast_log(LOG_DEBUG, "Sending 250ms dtmf!\n");
 	} else if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN) {
 		iks_insert_attrib(dtmf, "action", "button-down");
 	} else if (ast->dtmff.frametype == AST_FRAME_DTMF_END) {

Modified: team/group/vldtmf_fixup/channels/chan_h323.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_h323.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_h323.c (original)
+++ team/group/vldtmf_fixup/channels/chan_h323.c Wed Jan 17 15:28:34 2007
@@ -234,7 +234,7 @@
 
 static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause);
 static int oh323_digit_begin(struct ast_channel *c, char digit);
-static int oh323_digit_end(struct ast_channel *c, char digit);
+static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration);
 static int oh323_call(struct ast_channel *c, char *dest, int timeout);
 static int oh323_hangup(struct ast_channel *c);
 static int oh323_answer(struct ast_channel *c);
@@ -545,7 +545,7 @@
  * Send (play) the specified digit to the channel.
  *
  */
-static int oh323_digit_end(struct ast_channel *c, char digit)
+static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration)
 {
 	struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
 	char *token;

Modified: team/group/vldtmf_fixup/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_iax2.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_iax2.c (original)
+++ team/group/vldtmf_fixup/channels/chan_iax2.c Wed Jan 17 15:28:34 2007
@@ -776,7 +776,7 @@
 static int iax2_call(struct ast_channel *c, char *dest, int timeout);
 static int iax2_devicestate(void *data);
 static int iax2_digit_begin(struct ast_channel *c, char digit);
-static int iax2_digit_end(struct ast_channel *c, char digit);
+static int iax2_digit_end(struct ast_channel *c, char digit, unsigned int duration);
 static int iax2_do_register(struct iax2_registry *reg);
 static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan);
 static int iax2_hangup(struct ast_channel *c);
@@ -2388,7 +2388,7 @@
 	return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
 }
 
-static int iax2_digit_end(struct ast_channel *c, char digit)
+static int iax2_digit_end(struct ast_channel *c, char digit, unsigned int duration)
 {
 	return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
 }

Modified: team/group/vldtmf_fixup/channels/chan_local.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_local.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_local.c (original)
+++ team/group/vldtmf_fixup/channels/chan_local.c Wed Jan 17 15:28:34 2007
@@ -68,7 +68,7 @@
 
 static struct ast_channel *local_request(const char *type, int format, void *data, int *cause);
 static int local_digit_begin(struct ast_channel *ast, char digit);
-static int local_digit_end(struct ast_channel *ast, char digit);
+static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int local_call(struct ast_channel *ast, char *dest, int timeout);
 static int local_hangup(struct ast_channel *ast);
 static int local_answer(struct ast_channel *ast);
@@ -368,7 +368,7 @@
 	return res;
 }
 
-static int local_digit_end(struct ast_channel *ast, char digit)
+static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct local_pvt *p = ast->tech_pvt;
 	int res = -1;

Modified: team/group/vldtmf_fixup/channels/chan_mgcp.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_mgcp.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_mgcp.c (original)
+++ team/group/vldtmf_fixup/channels/chan_mgcp.c Wed Jan 17 15:28:34 2007
@@ -428,7 +428,7 @@
 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen);
 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit);
-static int mgcp_senddigit_end(struct ast_channel *ast, char digit);
+static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int mgcp_devicestate(void *data);
 
 static const struct ast_channel_tech mgcp_tech = {
@@ -1276,7 +1276,7 @@
 	return -1;
 }
 
-static int mgcp_senddigit_end(struct ast_channel *ast, char digit)
+static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct mgcp_subchannel *sub = ast->tech_pvt;
 	char tmp[4];

Modified: team/group/vldtmf_fixup/channels/chan_misdn.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_misdn.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_misdn.c (original)
+++ team/group/vldtmf_fixup/channels/chan_misdn.c Wed Jan 17 15:28:34 2007
@@ -2068,7 +2068,7 @@
 	return 0;
 }
 
-static int misdn_digit_end(struct ast_channel *ast, char digit )
+static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct chan_list *p;
 	

Modified: team/group/vldtmf_fixup/channels/chan_oss.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_oss.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_oss.c (original)
+++ team/group/vldtmf_fixup/channels/chan_oss.c Wed Jan 17 15:28:34 2007
@@ -408,7 +408,7 @@
 static struct ast_channel *oss_request(const char *type, int format, void *data
 , int *cause);
 static int oss_digit_begin(struct ast_channel *c, char digit);
-static int oss_digit_end(struct ast_channel *c, char digit);
+static int oss_digit_end(struct ast_channel *c, char digit, unsigned int duration);
 static int oss_text(struct ast_channel *c, const char *text);
 static int oss_hangup(struct ast_channel *c);
 static int oss_answer(struct ast_channel *c);
@@ -769,10 +769,11 @@
 	return 0;
 }
 
-static int oss_digit_end(struct ast_channel *c, char digit)
+static int oss_digit_end(struct ast_channel *c, char digit, unsigned int duration)
 {
 	/* no better use for received digits than print them */
-	ast_verbose(" << Console Received digit %c >> \n", digit);
+	ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 
+		digit, duration);
 	return 0;
 }
 

Modified: team/group/vldtmf_fixup/channels/chan_phone.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_phone.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_phone.c (original)
+++ team/group/vldtmf_fixup/channels/chan_phone.c Wed Jan 17 15:28:34 2007
@@ -159,7 +159,7 @@
 
 static struct ast_channel *phone_request(const char *type, int format, void *data, int *cause);
 static int phone_digit_begin(struct ast_channel *ast, char digit);
-static int phone_digit_end(struct ast_channel *ast, char digit);
+static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int phone_call(struct ast_channel *ast, char *dest, int timeout);
 static int phone_hangup(struct ast_channel *ast);
 static int phone_answer(struct ast_channel *ast);
@@ -246,12 +246,12 @@
 	return 0;
 }
 
-static int phone_digit_end(struct ast_channel *ast, char digit)
+static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct phone_pvt *p;
 	int outdigit;
 	p = ast->tech_pvt;
-	ast_log(LOG_NOTICE, "Dialed %c\n", digit);
+	ast_log(LOG_DEBUG, "Dialed %c\n", digit);
 	switch(digit) {
 	case '0':
 	case '1':
@@ -282,7 +282,7 @@
 		ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit);
 		return -1;
 	}
-	ast_log(LOG_NOTICE, "Dialed %d\n", outdigit);
+	ast_log(LOG_DEBUG, "Dialed %d\n", outdigit);
 	ioctl(p->fd, PHONE_PLAY_TONE, outdigit);
 	p->lastformat = -1;
 	return 0;
@@ -335,7 +335,7 @@
 		{
 		  digit++;
 		  while (*digit)
-		    phone_digit_end(ast, *digit++);
+		    phone_digit_end(ast, *digit++, 0);
 		}
 	}
  

Modified: team/group/vldtmf_fixup/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_sip.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_sip.c (original)
+++ team/group/vldtmf_fixup/channels/chan_sip.c Wed Jan 17 15:28:34 2007
@@ -1207,7 +1207,7 @@
 static int sip_transfer(struct ast_channel *ast, const char *dest);
 static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int sip_senddigit_begin(struct ast_channel *ast, char digit);
-static int sip_senddigit_end(struct ast_channel *ast, char digit);
+static int sip_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
 
 /*--- Transmitting responses and requests */
 static int sipsock_read(int *id, int fd, short events, void *ignore);
@@ -1229,7 +1229,7 @@
 static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch);
 static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init);
 static int transmit_reinvite_with_sdp(struct sip_pvt *p);
-static int transmit_info_with_digit(struct sip_pvt *p, const char digit);
+static int transmit_info_with_digit(struct sip_pvt *p, const char digit, unsigned int duration);
 static int transmit_info_with_vidupdate(struct sip_pvt *p);
 static int transmit_message_with_text(struct sip_pvt *p, const char *text);
 static int transmit_refer(struct sip_pvt *p, const char *dest);
@@ -1481,7 +1481,7 @@
 static int add_header_contentLength(struct sip_request *req, int len);
 static int add_line(struct sip_request *req, const char *line);
 static int add_text(struct sip_request *req, const char *text);
-static int add_digit(struct sip_request *req, char digit);
+static int add_digit(struct sip_request *req, char digit, unsigned int duration);
 static int add_vidupdate(struct sip_request *req);
 static void add_route(struct sip_request *req, struct sip_route *route);
 static int copy_header(struct sip_request *req, const struct sip_request *orig, const char *field);
@@ -1545,6 +1545,30 @@
 	.transfer = sip_transfer,
 	.fixup = sip_fixup,
 	.send_digit_begin = sip_senddigit_begin,
+	.send_digit_end = sip_senddigit_end,
+	.bridge = ast_rtp_bridge,
+	.send_text = sip_sendtext,
+};
+
+/*! \brief This version of the sip channel tech has no send_digit_begin
+ *  callback.  This is for use with channels using SIP INFO DTMF so that
+ *  the core knows that the channel doesn't want DTMF BEGIN frames. */
+static const struct ast_channel_tech sip_tech_info = {
+	.type = "SIP",
+	.description = "Session Initiation Protocol (SIP)",
+	.capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
+	.properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
+	.requester = sip_request_call,
+	.devicestate = sip_devicestate,
+	.call = sip_call,
+	.hangup = sip_hangup,
+	.answer = sip_answer,
+	.read = sip_read,
+	.write = sip_write,
+	.write_video = sip_write,
+	.indicate = sip_indicate,
+	.transfer = sip_transfer,
+	.fixup = sip_fixup,
 	.send_digit_end = sip_senddigit_end,
 	.bridge = ast_rtp_bridge,
 	.send_text = sip_sendtext,
@@ -3572,7 +3596,7 @@
 
 /*! \brief Send DTMF character on SIP channel
 	within one call, we're able to transmit in many methods simultaneously */
-static int sip_senddigit_end(struct ast_channel *ast, char digit)
+static int sip_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct sip_pvt *p = ast->tech_pvt;
 	int res = 0;
@@ -3580,7 +3604,7 @@
 	ast_mutex_lock(&p->lock);
 	switch (ast_test_flag(&p->flags[0], SIP_DTMF)) {
 	case SIP_DTMF_INFO:
-		transmit_info_with_digit(p, digit);
+		transmit_info_with_digit(p, digit, duration);
 		break;
 	case SIP_DTMF_RFC2833:
 		if (p->rtp)
@@ -3740,7 +3764,11 @@
 		ast_log(LOG_WARNING, "Unable to allocate AST channel structure for SIP channel\n");
 		return NULL;
 	}
-	tmp->tech = &sip_tech;
+
+	if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INFO)
+		tmp->tech = &sip_tech_info;
+	else
+		tmp->tech = &sip_tech;
 
 	/* Select our native format based on codec preference until we receive
 	   something from another device to the contrary. */
@@ -5819,11 +5847,11 @@
 
 /*! \brief Add DTMF INFO tone to sip message */
 /* Always adds default duration 250 ms, regardless of what came in over the line */
-static int add_digit(struct sip_request *req, char digit)
+static int add_digit(struct sip_request *req, char digit, unsigned int duration)
 {
 	char tmp[256];
 
-	snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=250\r\n", digit);
+	snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=%u\r\n", digit, duration);
 	add_header(req, "Content-Type", "application/dtmf-relay");
 	add_header_contentLength(req, strlen(tmp));
 	add_line(req, tmp);
@@ -7387,12 +7415,12 @@
 
 
 /*! \brief Send SIP INFO dtmf message, see Cisco documentation on cisco.com */
-static int transmit_info_with_digit(struct sip_pvt *p, const char digit)
+static int transmit_info_with_digit(struct sip_pvt *p, const char digit, unsigned int duration)
 {
 	struct sip_request req;
 
 	reqprep(&req, p, SIP_INFO, 0, 1);
-	add_digit(&req, digit);
+	add_digit(&req, digit, duration);
 	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
 }
 

Modified: team/group/vldtmf_fixup/channels/chan_skinny.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_skinny.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_skinny.c (original)
+++ team/group/vldtmf_fixup/channels/chan_skinny.c Wed Jan 17 15:28:34 2007
@@ -1032,7 +1032,7 @@
 static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen);
 static int skinny_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int skinny_senddigit_begin(struct ast_channel *ast, char digit);
-static int skinny_senddigit_end(struct ast_channel *ast, char digit);
+static int skinny_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
 
 static const struct ast_channel_tech skinny_tech = {
 	.type = "Skinny",
@@ -2566,7 +2566,7 @@
 	return -1; /* Start inband indications */
 }
 
-static int skinny_senddigit_end(struct ast_channel *ast, char digit)
+static int skinny_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 #if 0
 	struct skinny_subchannel *sub = ast->tech_pvt;

Modified: team/group/vldtmf_fixup/channels/chan_zap.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/channels/chan_zap.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/channels/chan_zap.c (original)
+++ team/group/vldtmf_fixup/channels/chan_zap.c Wed Jan 17 15:28:34 2007
@@ -700,7 +700,7 @@
 
 static struct ast_channel *zt_request(const char *type, int format, void *data, int *cause);
 static int zt_digit_begin(struct ast_channel *ast, char digit);
-static int zt_digit_end(struct ast_channel *ast, char digit);
+static int zt_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int zt_sendtext(struct ast_channel *c, const char *text);
 static int zt_call(struct ast_channel *ast, char *rdest, int timeout);
 static int zt_hangup(struct ast_channel *ast);
@@ -1086,7 +1086,7 @@
 	return 0;
 }
 
-static int zt_digit_end(struct ast_channel *chan, char digit)
+static int zt_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
 {
 	struct zt_pvt *pvt;
 	int res = 0;

Modified: team/group/vldtmf_fixup/include/asterisk/channel.h
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/include/asterisk/channel.h?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/include/asterisk/channel.h (original)
+++ team/group/vldtmf_fixup/include/asterisk/channel.h Wed Jan 17 15:28:34 2007
@@ -204,7 +204,7 @@
 	int (* const send_digit_begin)(struct ast_channel *chan, char digit);
 
 	/*! \brief Stop sending a literal DTMF digit */
-	int (* const send_digit_end)(struct ast_channel *chan, char digit);
+	int (* const send_digit_end)(struct ast_channel *chan, char digit, unsigned int duration);
 
 	/*! \brief Call a given phone number (address, etc), but don't
 	   take longer than timeout seconds to do so.  */
@@ -427,7 +427,8 @@
 	struct ast_jb jb;				/*!< The jitterbuffer state  */
 
 	char emulate_dtmf_digit;			/*!< Digit being emulated */
-	unsigned int emulate_dtmf_samples;		/*!< Number of samples left to emulate DTMF for */
+	unsigned int emulate_dtmf_duration;	/*!< Number of ms left to emulate DTMF for */
+	struct timeval dtmf_begin_tv;       /*!< The time that an in process digit began */
 
 	/*! \brief Data stores on the channel */
 	AST_LIST_HEAD_NOLOCK(datastores, ast_datastore) datastores;
@@ -446,34 +447,37 @@
 /*! \brief ast_channel flags */
 enum {
 	/*! Queue incoming dtmf, to be released when this flag is turned off */
-	AST_FLAG_DEFER_DTMF =   (1 << 1),
+	AST_FLAG_DEFER_DTMF =    (1 << 1),
 	/*! write should be interrupt generator */
-	AST_FLAG_WRITE_INT =    (1 << 2),
+	AST_FLAG_WRITE_INT =     (1 << 2),
 	/*! a thread is blocking on this channel */
-	AST_FLAG_BLOCKING =     (1 << 3),
+	AST_FLAG_BLOCKING =      (1 << 3),
 	/*! This is a zombie channel */
-	AST_FLAG_ZOMBIE =       (1 << 4),
+	AST_FLAG_ZOMBIE =        (1 << 4),
 	/*! There is an exception pending */
-	AST_FLAG_EXCEPTION =    (1 << 5),
+	AST_FLAG_EXCEPTION =     (1 << 5),
 	/*! Listening to moh XXX anthm promises me this will disappear XXX */
-	AST_FLAG_MOH =          (1 << 6),
+	AST_FLAG_MOH =           (1 << 6),
 	/*! This channel is spying on another channel */
-	AST_FLAG_SPYING =       (1 << 7),
+	AST_FLAG_SPYING =        (1 << 7),
 	/*! This channel is in a native bridge */
-	AST_FLAG_NBRIDGE =      (1 << 8),
+	AST_FLAG_NBRIDGE =       (1 << 8),
 	/*! the channel is in an auto-incrementing dialplan processor,
 	 *  so when ->priority is set, it will get incremented before
 	 *  finding the next priority to run */
-	AST_FLAG_IN_AUTOLOOP =  (1 << 9),
+	AST_FLAG_IN_AUTOLOOP =   (1 << 9),
 	/*! This is an outgoing call */
-	AST_FLAG_OUTGOING =     (1 << 10),
+	AST_FLAG_OUTGOING =      (1 << 10),
 	/*! This channel is being whispered on */
-	AST_FLAG_WHISPER =      (1 << 11),
+	AST_FLAG_WHISPER =       (1 << 11),
 	/*! A DTMF_BEGIN frame has been read from this channel, but not yet an END */
-	AST_FLAG_IN_DTMF =      (1 << 12),
+	AST_FLAG_IN_DTMF =       (1 << 12),
 	/*! A DTMF_END was received when not IN_DTMF, so the length of the digit is 
 	 *  currently being emulated */
-	AST_FLAG_EMULATE_DTMF = (1 << 13),
+	AST_FLAG_EMULATE_DTMF =  (1 << 13),
+	/*! This is set to tell the channel not to generate DTMF begin frames, and
+	 *  to instead only generate END frames. */
+	AST_FLAG_END_DTMF_ONLY = (1 << 14),
 };
 
 /*! \brief ast_bridge_config flags */
@@ -887,7 +891,7 @@
 int ast_senddigit(struct ast_channel *chan, char digit);
 
 int ast_senddigit_begin(struct ast_channel *chan, char digit);
-int ast_senddigit_end(struct ast_channel *chan, char digit);
+int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duration);
 
 /*! \brief Receives a text string from a channel
  * Read a string of text from a channel

Modified: team/group/vldtmf_fixup/include/asterisk/frame.h
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/include/asterisk/frame.h?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/include/asterisk/frame.h (original)
+++ team/group/vldtmf_fixup/include/asterisk/frame.h Wed Jan 17 15:28:34 2007
@@ -131,9 +131,9 @@
 	/*! Subclass, frame dependent */
 	int subclass;				
 	/*! Length of data */
-	int datalen;				
+	int datalen;
 	/*! Number of 8khz samples in this frame */
-	int samples;				
+	int samples;
 	/*! Was the data malloc'd?  i.e. should we free it when we discard the frame? */
 	int mallocd;				
 	/*! The number of bytes allocated for a malloc'd frame header */

Modified: team/group/vldtmf_fixup/main/channel.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/main/channel.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/main/channel.c (original)
+++ team/group/vldtmf_fixup/main/channel.c Wed Jan 17 15:28:34 2007
@@ -104,8 +104,8 @@
 AST_THREADSTORAGE(state2str_threadbuf, state2str_threadbuf_init);
 #define STATE2STR_BUFSIZE   32
 
-/* XXX 100ms ... this won't work with wideband support */
-#define AST_DEFAULT_EMULATE_DTMF_SAMPLES 800
+/*! 100ms */
+#define AST_DEFAULT_EMULATE_DTMF_DURATION 100
 
 struct chanlist {
 	const struct ast_channel_tech *tech;
@@ -2003,14 +2003,19 @@
 	if (!ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_EMULATE_DTMF | AST_FLAG_IN_DTMF) && 
 	    !ast_strlen_zero(chan->dtmfq)) {
 		/* We have DTMF that has been deferred.  Return it now */
-		chan->dtmff.frametype = AST_FRAME_DTMF_BEGIN;
 		chan->dtmff.subclass = chan->dtmfq[0];
 		/* Drop first digit from the buffer */
 		memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1);
 		f = &chan->dtmff;
-		ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
-		chan->emulate_dtmf_digit = f->subclass;
-		chan->emulate_dtmf_samples = AST_DEFAULT_EMULATE_DTMF_SAMPLES;
+		if (ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY))
+			chan->dtmff.frametype = AST_FRAME_DTMF_END;
+		else {
+			chan->dtmff.frametype = AST_FRAME_DTMF_BEGIN;
+			ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
+			chan->emulate_dtmf_digit = f->subclass;
+			chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION;
+			chan->dtmf_begin_tv = ast_tvnow();
+		}
 		goto done;
 	}
 	
@@ -2126,38 +2131,47 @@
 			break;
 		case AST_FRAME_DTMF_END:
 			ast_log(LOG_DTMF, "DTMF end '%c' received on %s\n", f->subclass, chan->name);
-			if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_EMULATE_DTMF)) {
+			/* Queue it up if DTMF is deffered, or if DTMF emulation is forced.
+			 * However, only let emulation be forced if the other end cares about BEGIN frames */
+			if ( ast_test_flag(chan, AST_FLAG_DEFER_DTMF) ||
+				(ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)) ) {
 				if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
 					chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
 				else
 					ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
 				ast_frfree(f);
 				f = &ast_null_frame;
-			} else if (!ast_test_flag(chan, AST_FLAG_IN_DTMF)) {
+			} else if (!ast_test_flag(chan, AST_FLAG_IN_DTMF | AST_FLAG_END_DTMF_ONLY)) {
 				f->frametype = AST_FRAME_DTMF_BEGIN;
 				ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
 				chan->emulate_dtmf_digit = f->subclass;
-				if (f->samples)
-					chan->emulate_dtmf_samples = f->samples;
+				chan->dtmf_begin_tv = ast_tvnow();
+				if (f->len)
+					chan->emulate_dtmf_duration = f->len;
 				else
-					chan->emulate_dtmf_samples = AST_DEFAULT_EMULATE_DTMF_SAMPLES;
-			} else 
+					chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION;
+			} else {
 				ast_clear_flag(chan, AST_FLAG_IN_DTMF);
+				if (!f->len)
+					f->len = ast_tvdiff_ms(chan->dtmf_begin_tv, ast_tvnow());
+			}
 			break;
 		case AST_FRAME_DTMF_BEGIN:
 			ast_log(LOG_DTMF, "DTMF begin '%c' received on %s\n", f->subclass, chan->name);
-			if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF)) {
+			if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_END_DTMF_ONLY)) {
 				ast_frfree(f);
 				f = &ast_null_frame;
-			} else 
+			} else {
 				ast_set_flag(chan, AST_FLAG_IN_DTMF);
+				chan->dtmf_begin_tv = ast_tvnow();
+			}
 			break;
 		case AST_FRAME_VOICE:
 			/* The EMULATE_DTMF flag must be cleared here as opposed to when the samples
 			 * first get to zero, because we want to make sure we pass at least one
 			 * voice frame through before starting the next digit, to ensure a gap
 			 * between DTMF digits. */
-			if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !chan->emulate_dtmf_samples) {
+			if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !chan->emulate_dtmf_duration) {
 				ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF);
 				chan->emulate_dtmf_digit = 0;
 			}
@@ -2166,12 +2180,12 @@
 				ast_frfree(f);
 				f = &ast_null_frame;
 			} else if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF)) {
-				if (f->samples >= chan->emulate_dtmf_samples) {
-					chan->emulate_dtmf_samples = 0;
+				if ((f->samples / 8) >= chan->emulate_dtmf_duration) { /* XXX 8kHz */
+					chan->emulate_dtmf_duration = 0;
 					f->frametype = AST_FRAME_DTMF_END;
 					f->subclass = chan->emulate_dtmf_digit;
 				} else {
-					chan->emulate_dtmf_samples -= f->samples;
+					chan->emulate_dtmf_duration -= f->samples / 8; /* XXX 8kHz */
 					ast_frfree(f);
 					f = &ast_null_frame;
 				}
@@ -2444,12 +2458,12 @@
 	return 0;
 }
 
-int ast_senddigit_end(struct ast_channel *chan, char digit)
+int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duration)
 {
 	int res = -1;
 
 	if (chan->tech->send_digit_end)
-		res = chan->tech->send_digit_end(chan, digit);
+		res = chan->tech->send_digit_end(chan, digit, duration);
 
 	if (res && chan->generator)
 		ast_playtones_stop(chan);
@@ -2463,7 +2477,7 @@
 	
 	ast_safe_sleep(chan, 100); /* XXX 100ms ... probably should be configurable */
 	
-	return ast_senddigit_end(chan, digit);
+	return ast_senddigit_end(chan, digit, 100);
 }
 
 int ast_prod(struct ast_channel *chan)
@@ -2540,7 +2554,7 @@
 	case AST_FRAME_DTMF_END:
 		ast_clear_flag(chan, AST_FLAG_BLOCKING);
 		ast_channel_unlock(chan);
-		res = ast_senddigit_end(chan, fr->subclass);
+		res = ast_senddigit_end(chan, fr->subclass, fr->len);
 		ast_channel_lock(chan);
 		CHECK_BLOCKING(chan);
 		break;
@@ -3823,6 +3837,11 @@
 			nexteventts = ast_tvsub(nexteventts, ast_samp2tv(config->play_warning, 1000));
 	}
 
+	if (!c0->tech->send_digit_begin)
+		ast_set_flag(c1, AST_FLAG_END_DTMF_ONLY);
+	if (!c1->tech->send_digit_begin)
+		ast_set_flag(c0, AST_FLAG_END_DTMF_ONLY);
+
 	for (/* ever */;;) {
 		struct timeval now = { 0, };
 		int to;
@@ -3972,6 +3991,9 @@
 		if (res != AST_BRIDGE_RETRY)
 			break;
 	}
+
+	ast_clear_flag(c0, AST_FLAG_END_DTMF_ONLY);
+	ast_clear_flag(c1, AST_FLAG_END_DTMF_ONLY);
 
 	c0->_bridge = NULL;
 	c1->_bridge = NULL;

Modified: team/group/vldtmf_fixup/main/rtp.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf_fixup/main/rtp.c?view=diff&rev=51200&r1=51199&r2=51200
==============================================================================
--- team/group/vldtmf_fixup/main/rtp.c (original)
+++ team/group/vldtmf_fixup/main/rtp.c Wed Jan 17 15:28:34 2007
@@ -140,7 +140,7 @@
 	char resp;
 	unsigned int lasteventendseqn;
 	int dtmfcount;
-	unsigned int dtmfduration;
+	unsigned int dtmfsamples;
 	/* DTMF Transmission Variables */
 	unsigned int lastdigitts;
 	char sending_digit;	/* boolean - are we sending digits */
@@ -619,7 +619,7 @@
 		if (option_debug)
 			ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr));
 		rtp->resp = 0;
-		rtp->dtmfduration = 0;
+		rtp->dtmfsamples = 0;
 		return &ast_null_frame;
 	}
 	if (option_debug)
@@ -709,18 +709,18 @@
 {
 	unsigned int event;
 	unsigned int event_end;
-	unsigned int duration;
+	unsigned int samples;
 	char resp = 0;
 	struct ast_frame *f = NULL;
 
-	/* Figure out event, event end, and duration */
+	/* Figure out event, event end, and samples */
 	event = ntohl(*((unsigned int *)(data)));
 	event >>= 24;
 	event_end = ntohl(*((unsigned int *)(data)));
 	event_end <<= 8;
 	event_end >>= 24;
-	duration = ntohl(*((unsigned int *)(data)));
-	duration &= 0xFFFF;
+	samples = ntohl(*((unsigned int *)(data)));
+	samples &= 0xFFFF;
 
 	/* Print out debug if turned on */
 	if (rtpdebug || option_debug > 2)
@@ -745,19 +745,19 @@
 			f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
 	} else if (event_end & 0x80 && rtp->lasteventendseqn != seqno && rtp->resp) {
 		f = send_dtmf(rtp, AST_FRAME_DTMF_END);
-		f->samples = duration;
+		f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */
 		rtp->resp = 0;
 		rtp->lasteventendseqn = seqno;
 	} else if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && event_end & 0x80 && rtp->lasteventendseqn != seqno) {
 		rtp->resp = resp;
 		f = send_dtmf(rtp, AST_FRAME_DTMF_END);
-		f->samples = duration;
+		f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */
 		rtp->resp = 0;
 		rtp->lasteventendseqn = seqno;
 	}
 
 	rtp->dtmfcount = dtmftimeout;
-	rtp->dtmfduration = duration;
+	rtp->dtmfsamples = samples;
 
 	return f;
 }
@@ -2000,7 +2000,7 @@
 	rtp->lasttxformat = 0;
 	rtp->lastrxformat = 0;
 	rtp->dtmfcount = 0;
-	rtp->dtmfduration = 0;
+	rtp->dtmfsamples = 0;
 	rtp->seqno = 0;
 	rtp->rxseqno = 0;
 }
@@ -3180,8 +3180,18 @@
 		audio_p1_res = AST_RTP_TRY_PARTIAL;
 	}
 
-	/* If both sides are not using the same method of DTMF transmission (ie: one is RFC2833, other is INFO... then we can not do direct media */
-	if (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) {
+	/* If both sides are not using the same method of DTMF transmission 
+	 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
+	 * --------------------------------------------------
+	 * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
+	 * |-----------|------------|-----------------------|
+	 * | Inband    | False      | True                  |
+	 * | RFC2833   | True       | True                  |
+	 * | SIP Info  | False      | False                 |
+	 * --------------------------------------------------
+	 */
+	if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
+		 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
 		audio_p0_res = AST_RTP_TRY_PARTIAL;
 		audio_p1_res = AST_RTP_TRY_PARTIAL;
 	}



More information about the asterisk-commits mailing list