[asterisk-commits] oej: branch oej/pine-pine-pine-pine-everywhere-pine-1.6.0 r312383 - in /team/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Apr 1 06:56:47 CDT 2011


Author: oej
Date: Fri Apr  1 06:56:36 2011
New Revision: 312383

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=312383
Log:
Adding the DTMF work

Modified:
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/apps/app_meetme.c
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/apps/app_senddtmf.c
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_h323.c
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_iax2.c
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_local.c
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_mgcp.c
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_sip.c
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/channel.h
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/frame.h
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/rtp.h
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/autoservice.c
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/channel.c
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/features.c
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/frame.c
    team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/rtp.c

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/apps/app_meetme.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/apps/app_meetme.c?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/apps/app_meetme.c (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/apps/app_meetme.c Fri Apr  1 06:56:36 2011
@@ -2668,7 +2668,7 @@
 					ret = 0;
 					ast_frfree(f);
 					break;
-				} else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END)
+				} else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_CONTINUE || f->frametype == AST_FRAME_DTMF_END)
 					&& confflags & CONFFLAG_PASS_DTMF) {
 					conf_queue_dtmf(conf, user, f);
 				} else if ((confflags & CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) {

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/apps/app_senddtmf.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/apps/app_senddtmf.c?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/apps/app_senddtmf.c (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/apps/app_senddtmf.c Fri Apr  1 06:56:36 2011
@@ -80,13 +80,17 @@
 "Description: Plays a dtmf digit on the specified channel.\n"
 "Variables: (all are required)\n"
 "	Channel: Channel name to send digit to\n"
+"	Duration: The length of the tone (100 MS default, optional)\n"
 "	Digit: The dtmf digit to play\n";
 
 static int manager_play_dtmf(struct mansession *s, const struct message *m)
 {
 	const char *channel = astman_get_header(m, "Channel");
 	const char *digit = astman_get_header(m, "Digit");
+	const char *duration = astman_get_header(m, "Duration");
 	struct ast_channel *chan = ast_get_channel_by_name_locked(channel);
+
+	int dtmfduration = 0;
 	
 	if (!chan) {
 		astman_send_error(s, m, "Channel not specified");
@@ -97,8 +101,11 @@
 		ast_channel_unlock(chan);
 		return 0;
 	}
+	if (!ast_strlen_zero(duration)) {
+		dtmfduration = atoi(duration);
+	}
 
-	ast_senddigit(chan, *digit, 0);
+	ast_senddigit(chan, *digit, dtmfduration);
 
 	ast_channel_unlock(chan);
 	astman_send_ack(s, m, "DTMF successfully queued");

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_h323.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_h323.c?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_h323.c (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_h323.c Fri Apr  1 06:56:36 2011
@@ -557,7 +557,7 @@
 		if (h323debug) {
 			ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s, duration %d\n", digit, c->name, duration);
 		}
-		ast_rtp_senddigit_end(pvt->rtp, digit);
+		ast_rtp_senddigit_end(pvt->rtp, digit, duration);
 		ast_mutex_unlock(&pvt->lock);
 	} else {
 		/* in-band DTMF */

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_iax2.c?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_iax2.c (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_iax2.c Fri Apr  1 06:56:36 2011
@@ -988,6 +988,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_continue(struct ast_channel *c, char digit, unsigned int duration);
 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);
@@ -1035,6 +1036,7 @@
 	.requester = iax2_request,
 	.devicestate = iax2_devicestate,
 	.send_digit_begin = iax2_digit_begin,
+	.send_digit_continue = iax2_digit_continue,
 	.send_digit_end = iax2_digit_end,
 	.send_text = iax2_sendtext,
 	.send_image = iax2_sendimage,
@@ -3914,6 +3916,11 @@
 static int iax2_digit_begin(struct ast_channel *c, char digit)
 {
 	return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
+}
+
+static int iax2_digit_continue(struct ast_channel *c, char digit, unsigned int duration)
+{
+	return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_CONTINUE, digit, 0, NULL, 0, -1);
 }
 
 static int iax2_digit_end(struct ast_channel *c, char digit, unsigned int duration)

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_local.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_local.c?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_local.c (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_local.c Fri Apr  1 06:56:36 2011
@@ -71,6 +71,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_continue(struct ast_channel *ast, char digit, unsigned int duration);
 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);
@@ -95,6 +96,7 @@
 	.capabilities = -1,
 	.requester = local_request,
 	.send_digit_begin = local_digit_begin,
+	.send_digit_continue = local_digit_continue,
 	.send_digit_end = local_digit_end,
 	.call = local_call,
 	.hangup = local_hangup,
@@ -596,6 +598,26 @@
 	return res;
 }
 
+static int local_digit_continue(struct ast_channel *ast, char digit, unsigned int duration)
+{
+	struct local_pvt *p = ast->tech_pvt;
+	int res = -1;
+	struct ast_frame f = { AST_FRAME_DTMF_CONTINUE, };
+	int isoutbound;
+
+	if (!p)
+		return -1;
+
+	ast_mutex_lock(&p->lock);
+	isoutbound = IS_OUTBOUND(ast, p);
+	f.subclass = digit;
+	f.len = duration;
+	if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0)))
+		ast_mutex_unlock(&p->lock);
+
+	return res;
+}
+
 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct local_pvt *p = ast->tech_pvt;

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_mgcp.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_mgcp.c?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_mgcp.c (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_mgcp.c Fri Apr  1 06:56:36 2011
@@ -424,6 +424,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_continue(struct ast_channel *ast, char digit, unsigned int duration);
 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int mgcp_devicestate(void *data);
 static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp);
@@ -443,6 +444,7 @@
 	.indicate = mgcp_indicate,
 	.fixup = mgcp_fixup,
 	.send_digit_begin = mgcp_senddigit_begin,
+	.send_digit_continue = mgcp_senddigit_continue,
 	.send_digit_end = mgcp_senddigit_end,
 	.bridge = ast_rtp_bridge,
 };
@@ -1330,6 +1332,21 @@
 	return res;
 }
 
+static int mgcp_senddigit_continue(struct ast_channel *ast, char digit, unsigned int duration)
+{
+	struct mgcp_subchannel *sub = ast->tech_pvt;
+	struct mgcp_endpoint *p = sub->parent;
+
+	ast_mutex_lock(&sub->lock);
+
+	if (p->dtmfmode & MGCP_DTMF_RFC2833) {
+		ast_debug(1, "DTMF continue using RFC2833\n");
+                ast_rtp_senddigit_continue(sub->rtp, digit, duration);
+	}
+	ast_mutex_unlock(&sub->lock);
+
+	return 0;
+}
 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct mgcp_subchannel *sub = ast->tech_pvt;
@@ -1348,7 +1365,7 @@
 		tmp[2] = digit;
 		tmp[3] = '\0';
 		transmit_notify_request(sub, tmp);
-                ast_rtp_senddigit_end(sub->rtp, digit);
+                ast_rtp_senddigit_end(sub->rtp, digit, duration);
 	} else {
 		ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
 	}

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_sip.c?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_sip.c (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/channels/chan_sip.c Fri Apr  1 06:56:36 2011
@@ -1731,6 +1731,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_continue(struct ast_channel *ast, char digit, unsigned int duration);
 static int sip_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int sip_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
 static const char *sip_get_callid(struct ast_channel *chan);
@@ -2135,6 +2136,7 @@
 	.transfer = sip_transfer,		/* called with chan locked */
 	.fixup = sip_fixup,			/* called with chan locked */
 	.send_digit_begin = sip_senddigit_begin,	/* called with chan unlocked */
+	.send_digit_continue = sip_senddigit_continue,	/* called with chan unlocked */
 	.send_digit_end = sip_senddigit_end,
 	.bridge = ast_rtp_bridge,			/* XXX chan unlocked ? */
 	.early_bridge = ast_rtp_early_bridge,
@@ -5497,6 +5499,26 @@
 	return res;
 }
 
+/*! \brief Update DTMF character on SIP channel
+	within one call, we're able to transmit in many methods simultaneously */
+static int sip_senddigit_continue(struct ast_channel *ast, char digit, unsigned int duration)
+{
+	struct sip_pvt *p = ast->tech_pvt;
+	int res = 0;
+
+	ast_log(LOG_DEBUG, " DTMF CONTINUE HERE!!! \n");
+
+	sip_pvt_lock(p);
+	switch (ast_test_flag(&p->flags[0], SIP_DTMF)) {
+	case SIP_DTMF_RFC2833:
+		if (p->rtp)
+			ast_rtp_senddigit_continue(p->rtp, digit, duration);
+		break;
+	}
+	sip_pvt_unlock(p);
+
+	return res;
+}
 /*! \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, unsigned int duration)
@@ -5512,7 +5534,7 @@
 		break;
 	case SIP_DTMF_RFC2833:
 		if (p->rtp)
-			ast_rtp_senddigit_end(p->rtp, digit);
+			ast_rtp_senddigit_end(p->rtp, digit, duration);
 		break;
 	case SIP_DTMF_INBAND:
 		res = -1; /* Tell Asterisk to stop inband indications */

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/channel.h?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/channel.h (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/channel.h Fri Apr  1 06:56:36 2011
@@ -271,6 +271,13 @@
 	 * \note The channel is not locked when this function gets called. 
 	 */
 	int (* const send_digit_begin)(struct ast_channel *chan, char digit);
+
+	/*! 
+	 * \brief Continue sending a literal DTMF digit 
+	 *
+	 * \note The channel is not locked when this function gets called. 
+	 */
+	int (* const send_digit_continue)(struct ast_channel *chan, char digit, unsigned int duration);
 
 	/*! 
 	 * \brief Stop sending a literal DTMF digit 
@@ -1254,6 +1261,15 @@
  */
 int ast_senddigit_begin(struct ast_channel *chan, char digit);
 
+/*! \brief Continue to send a DTMF digit to a channel
+ * used on RTP bridges mainly (to get the duration correct)
+ * Send a DTMF digit to a channel.
+ * \param chan channel to act upon
+ * \param digit the DTMF digit to send, encoded in ASCII
+ * \return Returns 0 on success, -1 on failure
+ */
+int ast_senddigit_continue(struct ast_channel *chan, char digit, unsigned int duration);
+
 /*! \brief Send a DTMF digit to a channel
 
  * Send a DTMF digit to a channel.

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/frame.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/frame.h?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/frame.h (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/frame.h Fri Apr  1 06:56:36 2011
@@ -121,6 +121,8 @@
 	AST_FRAME_MODEM,	
 	/*! DTMF begin event, subclass is the digit */
 	AST_FRAME_DTMF_BEGIN,
+	/*! DTMF continue event, subclass is the digit */
+	AST_FRAME_DTMF_CONTINUE,
 };
 #define AST_FRAME_DTMF AST_FRAME_DTMF_END
 

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/rtp.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/rtp.h?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/rtp.h (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/include/asterisk/rtp.h Fri Apr  1 06:56:36 2011
@@ -181,7 +181,9 @@
 
 int ast_rtp_senddigit_begin(struct ast_rtp *rtp, char digit);
 
-int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit);
+int ast_rtp_senddigit_continue(struct ast_rtp *rtp, char digit, unsigned int duration);
+
+int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit, unsigned int duration);
 
 int ast_rtp_sendcng(struct ast_rtp *rtp, int level);
 

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/autoservice.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/autoservice.c?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/autoservice.c (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/autoservice.c Fri Apr  1 06:56:36 2011
@@ -146,6 +146,7 @@
 
 			/* Throw these frames away */
 			case AST_FRAME_DTMF_BEGIN:
+			case AST_FRAME_DTMF_CONTINUE:
 			case AST_FRAME_VOICE:
 			case AST_FRAME_VIDEO:
 			case AST_FRAME_NULL:

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/channel.c?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/channel.c (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/channel.c Fri Apr  1 06:56:36 2011
@@ -1902,6 +1902,7 @@
 				case AST_FRAME_VIDEO:
 				case AST_FRAME_TEXT:
 				case AST_FRAME_DTMF_BEGIN:
+				case AST_FRAME_DTMF_CONTINUE:
 				case AST_FRAME_DTMF_END:
 				case AST_FRAME_IMAGE:
 				case AST_FRAME_HTML:
@@ -2454,6 +2455,7 @@
 
 			switch (f->frametype) {
 			case AST_FRAME_DTMF_BEGIN:
+			case AST_FRAME_DTMF_CONTINUE:
 				break;
 			case AST_FRAME_DTMF_END:
 				res = f->subclass;
@@ -2750,7 +2752,7 @@
 			 * there are cases where we want to leave DTMF frames on the queue until
 			 * some later time. */
 
-			if ( (f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) && skip_dtmf) {
+			if ( (f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_CONTINUE || f->frametype == AST_FRAME_DTMF_END) && skip_dtmf) {
 				continue;
 			}
 
@@ -2903,6 +2905,13 @@
 				}
 			}
 			break;
+		case AST_FRAME_DTMF_CONTINUE:
+			/* No manager event at this point
+				send_dtmf_event(chan, "Received", f->subclass, "Yes", "No");
+			*/
+			ast_log(LOG_DTMF, "DTMF continue '%c' received on %s\n", f->subclass, chan->name);
+			ast_log(LOG_DEBUG, "---DEBUG--- DTMF continue '%c' received on %s\n", f->subclass, chan->name);
+			break;
 		case AST_FRAME_DTMF_BEGIN:
 			send_dtmf_event(chan, "Received", f->subclass, "Yes", "No");
 			ast_log(LOG_DTMF, "DTMF begin '%c' received on %s\n", f->subclass, chan->name);
@@ -3345,6 +3354,17 @@
 	return 0;
 }
 
+int ast_senddigit_continue(struct ast_channel *chan, char digit, unsigned int duration)
+{
+	int res = -1;
+
+	ast_log(LOG_DEBUG, "DEBUG --- COntinue frame passed on to tech for %s\n", chan->name);
+	if (chan->tech->send_digit_continue)
+		res = chan->tech->send_digit_continue(chan, digit, duration);
+
+	return 0;
+}
+
 int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duration)
 {
 	int res = -1;
@@ -3466,6 +3486,22 @@
 		ast_clear_flag(chan, AST_FLAG_BLOCKING);
 		ast_channel_unlock(chan);
 		res = ast_senddigit_begin(chan, fr->subclass);
+		ast_channel_lock(chan);
+		CHECK_BLOCKING(chan);
+		break;
+	case AST_FRAME_DTMF_CONTINUE:
+		if (chan->audiohooks) {
+			struct ast_frame *old_frame = fr;
+			fr = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr);
+			if (old_frame != fr)
+				f = fr;
+		}
+		ast_log(LOG_DEBUG, "---Continue FRAME received, forwarding to channel %s", chan->name);
+		// Skip manager for continue events (at least for now)
+		//send_dtmf_event(chan, "Sent", fr->subclass, "Yes", "No");
+		ast_clear_flag(chan, AST_FLAG_BLOCKING);
+		ast_channel_unlock(chan);
+		res = ast_senddigit_continue(chan, fr->subclass, fr->len);
 		ast_channel_lock(chan);
 		CHECK_BLOCKING(chan);
 		break;
@@ -4904,6 +4940,7 @@
 		}
 		if ((f->frametype == AST_FRAME_VOICE) ||
 		    (f->frametype == AST_FRAME_DTMF_BEGIN) ||
+		    (f->frametype == AST_FRAME_DTMF_CONTINUE) ||
 		    (f->frametype == AST_FRAME_DTMF) ||
 		    (f->frametype == AST_FRAME_VIDEO) ||
 		    (f->frametype == AST_FRAME_IMAGE) ||
@@ -4919,7 +4956,7 @@
 				*fo = f;
 				*rc = who;
 				ast_debug(1, "Got DTMF %s on channel (%s)\n", 
-					f->frametype == AST_FRAME_DTMF_END ? "end" : "begin",
+					f->frametype == AST_FRAME_DTMF_END ? "end" : "begin",	/* BUG for continue. Ignored now. OEJ */
 					who->name);
 
 				break;

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/features.c?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/features.c (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/features.c Fri Apr  1 06:56:36 2011
@@ -1794,7 +1794,9 @@
 			if (operation) {
 				res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
 			}
-			memcpy(feature, tmpfeature, sizeof(feature));
+			if (feature) {
+				memcpy(feature, tmpfeature, sizeof(feature));
+			}
 			if (res != AST_FEATURE_RETURN_KEEPTRYING) {
 				AST_RWLIST_UNLOCK(&feature_list);
 				break;
@@ -2205,6 +2207,7 @@
 	int hasfeatures=0;
 	int hadfeatures=0;
 	int autoloopflag;
+	int sendingdtmfdigit = 0;
 	struct ast_option_header *aoh;
 	struct ast_bridge_config backup_config;
 	struct ast_cdr *bridge_cdr = NULL;
@@ -2389,11 +2392,11 @@
 					   digits to come in for features. */
 					ast_debug(1, "Timed out for feature!\n");
 					if (!ast_strlen_zero(peer_featurecode)) {
-						ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
+						ast_dtmf_stream(chan, peer, peer_featurecode, 0, f->len);
 						memset(peer_featurecode, 0, sizeof(peer_featurecode));
 					}
 					if (!ast_strlen_zero(chan_featurecode)) {
-						ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
+						ast_dtmf_stream(peer, chan, chan_featurecode, 0, f->len);
 						memset(chan_featurecode, 0, sizeof(chan_featurecode));
 					}
 					if (f)
@@ -2459,11 +2462,10 @@
 				}
 				break;
 			}
-		} else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
-			/* eat it */
-		} else if (f->frametype == AST_FRAME_DTMF) {
+		} else if (f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_DTMF_BEGIN) {
 			char *featurecode;
 			int sense;
+			unsigned int dtmfduration = f->len;
 
 			hadfeatures = hasfeatures;
 			/* This cannot overrun because the longest feature is one shorter than our buffer */
@@ -2479,14 +2481,24 @@
 			 * \todo XXX how do we guarantee the latter ?
 			 */
 			featurecode[strlen(featurecode)] = f->subclass;
+			config->feature_timer = backup_config.feature_timer;
+
+			if (f->frametype == AST_FRAME_DTMF_BEGIN) {
+				/* Take a peek if this is the beginning of a feature. If not, just pass this DTMF along untouched. */
+				res = ast_feature_detect(chan, sense == FEATURE_SENSE_CHAN ? &(config->features_caller) : &(config->features_callee),featurecode, NULL);
+				if (res == FEATURE_RETURN_PASSDIGITS) {
+					ast_log(LOG_DEBUG, "We are doing nothing here, but this DTMF is not a feature code\n");
+				}
+				break;
+			}
 			/* Get rid of the frame before we start doing "stuff" with the channels */
 			ast_frfree(f);
 			f = NULL;
-			config->feature_timer = backup_config.feature_timer;
 			res = ast_feature_interpret(chan, peer, config, featurecode, sense);
 			switch(res) {
 			case FEATURE_RETURN_PASSDIGITS:
-				ast_dtmf_stream(other, who, featurecode, 0, 0);
+				ast_log(LOG_DEBUG, "--- Sending DTMF here - 3 Duration %d\n", dtmfduration);
+				ast_dtmf_stream(other, who, featurecode, 0, dtmfduration);
 				/* Fall through */
 			case FEATURE_RETURN_SUCCESS:
 				memset(featurecode, 0, sizeof(chan_featurecode));

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/frame.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/frame.c?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/frame.c (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/frame.c Fri Apr  1 06:56:36 2011
@@ -769,6 +769,11 @@
 		subclass[0] = f->subclass;
 		subclass[1] = '\0';
 		break;
+	case AST_FRAME_DTMF_CONTINUE:
+		strcpy(ftype, "DTMF Continue");
+		subclass[0] = f->subclass;
+		subclass[1] = '\0';
+		break;
 	case AST_FRAME_DTMF_END:
 		strcpy(ftype, "DTMF End");
 		subclass[0] = f->subclass;

Modified: team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/rtp.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/rtp.c?view=diff&rev=312383&r1=312382&r2=312383
==============================================================================
--- team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/rtp.c (original)
+++ team/oej/pine-pine-pine-pine-everywhere-pine-1.6.0/main/rtp.c Fri Apr  1 06:56:36 2011
@@ -144,8 +144,11 @@
 	unsigned int lastdigitts;
 	char sending_digit;	/*!< boolean - are we sending digits */
 	char send_digit;	/*!< digit we are sending */
+	char send_dtmf_frame;	/*!< Number of samples in a frame with the current packetization */
 	int send_payload;
 	int send_duration;
+	int send_endflag:1;	/*!< We have received END marker but are in waiting mode */
+	unsigned int received_duration;	/*!< Received duration (according to control frames) */
 	int nat;
 	unsigned int flags;
 	struct sockaddr_in us;		/*!< Socket representation of the local endpoint. */
@@ -190,7 +193,6 @@
 static int ast_rtcp_write_rr(const void *data);
 static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp);
 static int ast_rtp_senddigit_continuation(struct ast_rtp *rtp);
-int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit);
 
 #define FLAG_3389_WARNING		(1 << 0)
 #define FLAG_NAT_ACTIVE			(3 << 1)
@@ -805,7 +807,7 @@
 		rtp->dtmfsamples = 0;
 		return &ast_null_frame;
 	}
-	ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr));
+	ast_debug(1, "Sending dtmf: %d (%c), at %s \n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr));
 	if (rtp->resp == 'X') {
 		rtp->f.frametype = AST_FRAME_CONTROL;
 		rtp->f.subclass = AST_CONTROL_FLASH;
@@ -1014,6 +1016,7 @@
 				f = ast_frdup(create_dtmf_frame(rtp, AST_FRAME_DTMF_END));
 				f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
 				rtp->resp = 0;
+				ast_log(LOG_DEBUG, "--GOT DTMF END message. Duration samples %d (%ld ms)\n", rtp->dtmf_duration, f->len);
 				rtp->dtmf_duration = rtp->dtmf_timeout = 0;
 				AST_LIST_INSERT_TAIL(frames, f, frame_list);
 			}
@@ -1033,6 +1036,10 @@
 			if (rtp->resp) {
 				/* Digit continues */
 				rtp->dtmf_duration = new_duration;
+				f = ast_frdup(create_dtmf_frame(rtp, AST_FRAME_DTMF_CONTINUE));
+				f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
+				AST_LIST_INSERT_TAIL(frames, f, frame_list);
+				ast_log(LOG_DEBUG, "Queued frame AST_FRAME_DTMF_CONTINUE, Samples %d Ms %d\n", rtp->dtmf_duration, (int)f->len);
 			} else {
 				/* New digit began */
 				rtp->resp = resp;
@@ -1448,9 +1455,18 @@
 	struct ast_rtp *bridged = NULL;
 	struct frame_list frames;
 	
-	/* If time is up, kill it */
-	if (rtp->sending_digit)
+	if (rtp->sending_digit > 1) {
 		ast_rtp_senddigit_continuation(rtp);
+	} else {
+		/* Skip the first one due to possible BEGIN retransmits 
+	   	Yes, this is a poor coding solution, more of a bad hack.
+	   	Tests have shown that there's always one CONT packet sent without an incoming CONT
+	   	right after we've sent the BEGIN. Un-needed.
+		*/
+		if (rtp->sending_digit == 1)  {
+			rtp->sending_digit = 2;
+		}
+	}
 
 	len = sizeof(sin);
 	
@@ -2710,10 +2726,8 @@
 				    ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
 		/* Increment sequence number */
 		rtp->seqno++;
-		/* Increment duration */
-		rtp->send_duration += 160;
-		/* Clear marker bit and set seqno */
-		rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
+		/* Raise the seqno */
+		rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
 	}
 
 	/* Since we received a begin, we can safely store the digit and disable any compensation */
@@ -2721,6 +2735,32 @@
 	rtp->send_digit = digit;
 	rtp->send_payload = payload;
 
+	ast_log(LOG_DEBUG, "DEBUG DTMF BEGIN - Digit %d send-digit %d\n", digit, rtp->send_digit);
+
+	return 0;
+}
+
+/*! \brief Get notification of duration updates */
+int ast_rtp_senddigit_continue(struct ast_rtp *rtp, char digit, unsigned int duration)
+{
+	ast_log(LOG_DEBUG, "DEBUG DTMF CONTINUE - Duration %d Digit %d Send-digit %d\n", duration, digit, rtp->send_digit);
+
+	/* Duration is in ms. Calculate the duration in timestamps */
+	if (duration > 0) {
+		/* We have an incoming duration from the incoming channel. This needs
+		   to be matched with our outbound pacing. The inbound can be paced
+		   in either 50 ms or whatever packetization that is used on that channel,
+		   so we can't assume 20 ms (160 units in 8000 hz audio).
+		*/
+		// int dursamples =  duration * (rtp_get_rate(f->subclass) / 1000)
+		int dursamples =  duration * (rtp_get_rate(rtp->f.subclass) / 1000);	/* How do we get the sample rate for the primary media in this call? */
+
+		ast_log(LOG_DEBUG, "DTMF CONTINUE : %d ms %d samples\n", duration, dursamples);
+		rtp->received_duration = dursamples;
+	} else {
+		ast_log(LOG_DEBUG, "DTMF CONTINUE : Missing duration!!!!!!!\n");
+		
+	}
 	return 0;
 }
 
@@ -2733,6 +2773,18 @@
 
 	if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
 		return 0;
+
+	ast_log(LOG_DEBUG, "---- Send duration %d Received duration %d Endflag %d Send-digit %d\n", rtp->send_duration, rtp->received_duration, rtp->send_endflag, rtp->send_digit);
+
+	if (rtp->received_duration == 0 || rtp->send_duration + 160 <= rtp->received_duration) {
+		rtp->send_duration += 160;
+	} else if (rtp->send_endflag) {
+		ast_log(LOG_DEBUG, "---- Send duration %d Received duration %d - sending END packet\n", rtp->send_duration, rtp->received_duration);
+		/* We are done, ready to send end flag */
+		rtp->send_endflag = 0;
+		return ast_rtp_senddigit_end(rtp, 0, rtp->received_duration);
+	}
+
 
 	/* Setup packet to send */
 	rtpheader = (unsigned int *)data;
@@ -2755,39 +2807,68 @@
 
 	/* Increment sequence number */
 	rtp->seqno++;
-	/* Increment duration */
-	rtp->send_duration += 160;
 
 	return 0;
 }
 
 /*! \brief Send end packets for DTMF */
-int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit)
+int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit, unsigned int duration)
 {
 	unsigned int *rtpheader;
 	int hdrlen = 12, res = 0, i = 0;
 	char data[256];
+
+	int dursamples =  duration * (8000 / 1000);	/* How do we get the sample rate for the primary media in this call? */
 	
 	/* If no address, then bail out */
 	if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
 		return 0;
-	
-	if ((digit <= '9') && (digit >= '0'))
-		digit -= '0';
-	else if (digit == '*')
-		digit = 10;
-	else if (digit == '#')
-		digit = 11;
-	else if ((digit >= 'A') && (digit <= 'D'))
-		digit = digit - 'A' + 12;
-	else if ((digit >= 'a') && (digit <= 'd'))
-		digit = digit - 'a' + 12;
-	else {
-		ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
-		return 0;
+
+
+	ast_log(LOG_DEBUG, "---- Send duration %d Received duration %d Duration %d Endflag %d Digit %d Send-digit %d\n", rtp->send_duration, rtp->received_duration, duration, rtp->send_endflag, digit, rtp->send_digit);
+
+	//if (dursamples > rtp->received_duration) {
+		//rtp->received_duration = dursamples;
+	//}
+
+	if (!rtp->send_endflag && rtp->send_duration + 160 < rtp->received_duration) {
+		/* We still have to send DTMF continuation, because otherwise we will end prematurely. Set end flag to indicate
+		   that we will have to end ourselves when we're done with the actual duration
+		 */
+		ast_log(LOG_DEBUG, "---- Send duration %d Received duration %d - Avoiding sending END packet\n", rtp->send_duration, rtp->received_duration);
+		rtp->send_endflag = 1;
+		return ast_rtp_senddigit_continuation(rtp);
+	}
+
+	if (digit) {
+		if ((digit <= '9') && (digit >= '0'))
+			digit -= '0';
+		else if (digit == '*')
+			digit = 10;
+		else if (digit == '#')
+			digit = 11;
+		else if ((digit >= 'A') && (digit <= 'D'))
+			digit = digit - 'A' + 12;
+		else if ((digit >= 'a') && (digit <= 'd'))
+			digit = digit - 'a' + 12;
+		else {
+			ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
+			rtp->sending_digit = 0;
+			rtp->send_digit = 0;
+			rtp->received_duration = 0;
+			return 0;
+		}
+	} else {
+		digit = rtp->send_digit;
 	}
 
 	rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
+
+	rtp->send_duration += 160;
+
+	if (rtp->received_duration > rtp->send_duration) {
+		rtp->send_duration = rtp->received_duration;
+	}
 
 	rtpheader = (unsigned int *)data;
 	rtpheader[1] = htonl(rtp->lastdigitts);
@@ -2810,9 +2891,11 @@
 				    ast_inet_ntoa(rtp->them.sin_addr),
 				    ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
 	}
+	ast_log(LOG_DEBUG, "-- DTMF END: Duration samples sent %d got %d ms (%d samples)\n", rtp->send_duration, duration, dursamples);
 	rtp->lastts += rtp->send_duration;
 	rtp->sending_digit = 0;
 	rtp->send_digit = 0;
+	rtp->received_duration = 0;
 
 	return res;
 }




More information about the asterisk-commits mailing list