[svn-commits] kpfleming: trunk r201139 - in /trunk: apps/ channels/ include/asterisk/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Jun 16 16:10:19 CDT 2009


Author: kpfleming
Date: Tue Jun 16 16:10:15 2009
New Revision: 201139

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=201139
Log:
Enable applications to enable/disable digit and tone detection.

Some applications (notably app_fax) do not need digit detection nor FAX tone
detection while they are running, and if Asterisk is using software DSPs to provide
the detection, this consumes extra CPU cycles that could be better spent on the
actual application. This patch allows applications to query and control the state
of digit and tone detection on a channel, and modifies app_fax to disable them
while the FAX operations are occurring (and re-enable digit detection afterwards).


Modified:
    trunk/apps/app_fax.c
    trunk/channels/chan_dahdi.c
    trunk/channels/chan_sip.c
    trunk/include/asterisk/frame.h

Modified: trunk/apps/app_fax.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/apps/app_fax.c?view=diff&rev=201139&r1=201138&r2=201139
==============================================================================
--- trunk/apps/app_fax.c (original)
+++ trunk/apps/app_fax.c Tue Jun 16 16:10:15 2009
@@ -710,6 +710,7 @@
 	int res = 0;
 	char *parse;
 	fax_session session;
+	char restore_digit_detect = 0;
 
 	AST_DECLARE_APP_ARGS(args,
 		AST_APP_ARG(file_name);
@@ -744,7 +745,31 @@
 	session.chan = chan;
 	session.finished = 0;
 
+	/* get current digit detection mode, then disable digit detection if enabled */
+	{
+		int dummy = sizeof(restore_digit_detect);
+
+		ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
+	}
+
+	if (restore_digit_detect) {
+		char new_digit_detect = 0;
+
+		ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
+	}
+
+	/* disable FAX tone detection if enabled */
+	{
+		char new_fax_detect = 0;
+
+		ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
+	}
+
 	res = transmit(&session);
+
+	if (restore_digit_detect) {
+		ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
+	}
 
 	return res;
 }
@@ -754,6 +779,7 @@
 	int res = 0;
 	char *parse;
 	fax_session session;
+	char restore_digit_detect = 0;
 
 	AST_DECLARE_APP_ARGS(args,
 		AST_APP_ARG(file_name);
@@ -788,7 +814,31 @@
 	session.chan = chan;
 	session.finished = 0;
 
+	/* get current digit detection mode, then disable digit detection if enabled */
+	{
+		int dummy = sizeof(restore_digit_detect);
+
+		ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
+	}
+
+	if (restore_digit_detect) {
+		char new_digit_detect = 0;
+
+		ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
+	}
+
+	/* disable FAX tone detection if enabled */
+	{
+		char new_fax_detect = 0;
+
+		ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
+	}
+
 	res = transmit(&session);
+
+	if (restore_digit_detect) {
+		ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
+	}
 
 	return res;
 }

Modified: trunk/channels/chan_dahdi.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/channels/chan_dahdi.c?view=diff&rev=201139&r1=201138&r2=201139
==============================================================================
--- trunk/channels/chan_dahdi.c (original)
+++ trunk/channels/chan_dahdi.c Tue Jun 16 16:10:15 2009
@@ -1507,6 +1507,7 @@
 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
+static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
 static int handle_init_event(struct dahdi_pvt *i, int event);
 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
@@ -1529,6 +1530,7 @@
 	.indicate = dahdi_indicate,
 	.fixup = dahdi_fixup,
 	.setoption = dahdi_setoption,
+	.queryoption = dahdi_queryoption,
 	.func_channel_read = dahdi_func_read,
 	.func_channel_write = dahdi_func_write,
 };
@@ -5890,6 +5892,66 @@
 	return res;
 }
 
+static void disable_dtmf_detect(struct dahdi_pvt *p)
+{
+	int val = 0;
+
+	p->ignoredtmf = 1;
+
+	ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
+
+	if (!p->hardwaredtmf && p->dsp) {
+		p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
+		ast_dsp_set_features(p->dsp, p->dsp_features);
+	}
+}
+
+static void enable_dtmf_detect(struct dahdi_pvt *p)
+{
+	int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
+
+	if (p->channel == CHAN_PSEUDO)
+		return;
+
+	p->ignoredtmf = 0;
+
+	ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
+
+	if (!p->hardwaredtmf && p->dsp) {
+		p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
+		ast_dsp_set_features(p->dsp, p->dsp_features);
+	}
+}
+
+static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
+{
+	char *cp;
+	struct dahdi_pvt *p = chan->tech_pvt;
+
+	/* all supported options require data */
+	if (!data || (*datalen < 1)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	switch (option) {
+	case AST_OPTION_DIGIT_DETECT:
+		cp = (char *) data;
+		*cp = p->ignoredtmf ? 0 : 1;
+		ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
+		break;
+	case AST_OPTION_FAX_DETECT:
+		cp = (char *) data;
+		*cp = (p->callprogress & CALLPROGRESS_FAX) ? 0 : 1;
+		ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
+		break;
+	}
+
+	errno = 0;
+
+	return 0;
+}
+
 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
 {
 	char *cp;
@@ -6072,6 +6134,29 @@
 			dahdi_disable_ec(p);
 		}
 		break;
+	case AST_OPTION_DIGIT_DETECT:
+		cp = (char *) data;
+		ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
+		if (*cp) {
+			enable_dtmf_detect(p);
+		} else {
+			disable_dtmf_detect(p);
+		}
+		break;
+	case AST_OPTION_FAX_DETECT:
+		cp = (char *) data;
+		if (p->dsp) {
+			ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
+			if (*cp) {
+				p->callprogress |= CALLPROGRESS_FAX;
+				p->dsp_features |= DSP_FEATURE_FAX_DETECT;
+			} else {
+				p->callprogress &= ~CALLPROGRESS_FAX;
+				p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
+			}
+			ast_dsp_set_features(p->dsp, p->dsp_features);
+		}
+		break;
 	default:
 		return -1;
 	}
@@ -6277,39 +6362,6 @@
 	slave->master = master;
 
 	ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
-}
-
-static void disable_dtmf_detect(struct dahdi_pvt *p)
-{
-	int val;
-
-	p->ignoredtmf = 1;
-
-	val = 0;
-	ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
-
-	if (!p->hardwaredtmf && p->dsp) {
-		p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
-		ast_dsp_set_features(p->dsp, p->dsp_features);
-	}
-}
-
-static void enable_dtmf_detect(struct dahdi_pvt *p)
-{
-	int val;
-
-	if (p->channel == CHAN_PSEUDO)
-		return;
-
-	p->ignoredtmf = 0;
-
-	val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
-	ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
-
-	if (!p->hardwaredtmf && p->dsp) {
-		p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
-		ast_dsp_set_features(p->dsp, p->dsp_features);
-	}
 }
 
 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
@@ -6814,6 +6866,10 @@
 				}
 			}
 			p->faxhandled = 1;
+			p->callprogress &= ~CALLPROGRESS_FAX;
+			p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
+			ast_dsp_set_features(p->dsp, p->dsp_features);
+			ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
 			if (strcmp(ast->exten, "fax")) {
 				const char *target_context = S_OR(ast->macrocontext, ast->context);
 

Modified: trunk/channels/chan_sip.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/channels/chan_sip.c?view=diff&rev=201139&r1=201138&r2=201139
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Tue Jun 16 16:10:15 2009
@@ -1833,7 +1833,7 @@
 	int laststate;				/*!< SUBSCRIBE: Last known extension state */
 	int dialogver;				/*!< SUBSCRIBE: Version for subscription dialog-info */
 
-	struct ast_dsp *vad;			/*!< Inband DTMF Detection dsp */
+	struct ast_dsp *dsp;			/*!< Inband DTMF Detection dsp */
 
 	struct sip_peer *relatedpeer;		/*!< If this dialog is related to a peer, which one 
 							Used in peerpoke, mwi subscriptions */
@@ -4076,21 +4076,62 @@
 	return res;
 }
 
+static void enable_digit_detect(struct sip_pvt *p)
+{
+	if (p->dsp) {
+		return;
+	}
+
+	if (!(p->dsp = ast_dsp_new())) {
+		return;
+	}
+
+	ast_dsp_set_features(p->dsp, DSP_FEATURE_DIGIT_DETECT);
+	if (global_relaxdtmf) {
+		ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
+	}
+}
+
+static void disable_digit_detect(struct sip_pvt *p)
+{
+	if (p->dsp) {
+		ast_dsp_free(p->dsp);
+		p->dsp = NULL;
+	}
+}
+
 /*! \brief Set an option on a SIP dialog */
 static int sip_setoption(struct ast_channel *chan, int option, void *data, int datalen)
 {
 	int res = -1;
 	struct sip_pvt *p = chan->tech_pvt;
 
-	if (option == AST_OPTION_FORMAT_READ) {
-		int format = *(int *)data;
-		res = ast_rtp_instance_set_read_format(p->rtp, format);
-	} else if (option == AST_OPTION_FORMAT_WRITE) {
-		int format = *(int *)data;
-		res = ast_rtp_instance_set_write_format(p->rtp, format);
-	} else if (option == AST_OPTION_MAKE_COMPATIBLE) {
-		struct ast_channel *peer = data;
-		res = ast_rtp_instance_make_compatible(chan, p->rtp, peer);
+	switch (option) {
+	case AST_OPTION_FORMAT_READ:
+		res = ast_rtp_instance_set_read_format(p->rtp, *(int *) data);
+		break;
+	case AST_OPTION_FORMAT_WRITE:
+		res = ast_rtp_instance_set_write_format(p->rtp, *(int *) data);
+		break;
+	case AST_OPTION_MAKE_COMPATIBLE:
+		res = ast_rtp_instance_make_compatible(chan, p->rtp, (struct ast_channel *) data);
+		break;
+	case AST_OPTION_DIGIT_DETECT:
+		if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
+		    (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
+			char *cp = (char *) data;
+
+			ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
+			if (*cp) {
+				enable_digit_detect(p);
+			} else {
+				disable_digit_detect(p);
+			}
+			res = 0;
+		}
+		break;
+	default:
+		break;
 	}
 
 	return res;
@@ -4102,6 +4143,7 @@
 	int res = -1;
 	enum ast_t38_state state = T38_STATE_UNAVAILABLE;
 	struct sip_pvt *p = (struct sip_pvt *) chan->tech_pvt;
+	char *cp;
 
 	switch (option) {
 	case AST_OPTION_T38_STATE:
@@ -4134,6 +4176,11 @@
 		*((enum ast_t38_state *) data) = state;
 		res = 0;
 
+		break;
+	case AST_OPTION_DIGIT_DETECT:
+		cp = (char *) data;
+		*cp = p->dsp ? 1 : 0;
+		ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
 		break;
 	default:
 		break;
@@ -5823,7 +5870,6 @@
 	return 0;
 }
 
-
 /*! \brief  sip_hangup: Hangup SIP call
  * Part of PBX interface, called from ast_hangup */
 static int sip_hangup(struct ast_channel *ast)
@@ -5902,8 +5948,7 @@
 	append_history(p, needcancel ? "Cancel" : "Hangup", "Cause %s", p->owner ? ast_cause2str(p->hangupcause) : "Unknown");
 
 	/* Disconnect */
-	if (p->vad)
-		ast_dsp_free(p->vad);
+	disable_digit_detect(p);
 
 	p->owner = NULL;
 	ast->tech_pvt = dialog_unref(ast->tech_pvt, "unref ast->tech_pvt");
@@ -6453,7 +6498,6 @@
 	return res;
 }
 
-
 /*! \brief Initiate a call in the SIP channel
 	called from sip_request_call (calls from the pbx ) for outbound channels
 	and from handle_request_invite for inbound channels
@@ -6552,12 +6596,10 @@
 	else
 		ast_debug(3, "This channel will not be able to handle video.\n");
 
-	if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
+	if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
+	    (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
 		if (!i->rtp || ast_rtp_instance_dtmf_mode_set(i->rtp, AST_RTP_DTMF_MODE_INBAND)) {
-			i->vad = ast_dsp_new();
-			ast_dsp_set_features(i->vad, DSP_FEATURE_DIGIT_DETECT);
-			if (global_relaxdtmf)
-				ast_dsp_set_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
+			enable_digit_detect(i);
 		}
 	} else if (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) {
 		if (i->rtp) {
@@ -6853,8 +6895,8 @@
 		ast_set_write_format(p->owner, p->owner->writeformat);
 	}
 
-	if (f && (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
-		f = ast_dsp_process(p->owner, p->vad, f);
+	if (f && p->dsp) {
+		f = ast_dsp_process(p->owner, p->dsp, f);
 		if (f && f->frametype == AST_FRAME_DTMF) {
 			if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_UDPTL) && f->subclass == 'f') {
 				ast_debug(1, "Fax CNG detected on %s\n", ast->name);
@@ -25354,16 +25396,11 @@
 		ast_log(LOG_WARNING, "I don't know about this dtmf mode: %s\n", mode);
 	if (p->rtp)
 		ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
-	if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) {
-		if (!p->vad) {
-			p->vad = ast_dsp_new();
-			ast_dsp_set_features(p->vad, DSP_FEATURE_DIGIT_DETECT);
-		}
+	if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
+	    (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
+		enable_digit_detect(p);
 	} else {
-		if (p->vad) {
-			ast_dsp_free(p->vad);
-			p->vad = NULL;
-		}
+		disable_digit_detect(p);
 	}
 	sip_pvt_unlock(p);
 	ast_channel_unlock(chan);

Modified: trunk/include/asterisk/frame.h
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/include/asterisk/frame.h?view=diff&rev=201139&r1=201138&r2=201139
==============================================================================
--- trunk/include/asterisk/frame.h (original)
+++ trunk/include/asterisk/frame.h Tue Jun 16 16:10:15 2009
@@ -400,6 +400,12 @@
 /*! Request that the channel driver make two channels of the same tech type compatible if possible */
 #define AST_OPTION_MAKE_COMPATIBLE      13
 
+/*! Get or set the digit detection state of the channel */
+#define AST_OPTION_DIGIT_DETECT		14
+
+/*! Get or set the fax tone detection state of the channel */
+#define AST_OPTION_FAX_DETECT		15
+
 struct oprmode {
 	struct ast_channel *peer;
 	int mode;




More information about the svn-commits mailing list