summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin P. Fleming <kpfleming@digium.com>2009-06-16 21:10:15 +0000
committerKevin P. Fleming <kpfleming@digium.com>2009-06-16 21:10:15 +0000
commitf1dc620467d9b218ad5041b6416bb030aec9c68c (patch)
treeb922d4113cce5ce50a4adcda3b8bcf400ab25b47
parent5b2939916fe602bb9dfd2ff6c5d40a594b3bd768 (diff)
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). git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@201139 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--apps/app_fax.c50
-rw-r--r--channels/chan_dahdi.c122
-rw-r--r--channels/chan_sip.c97
-rw-r--r--include/asterisk/frame.h6
4 files changed, 212 insertions, 63 deletions
diff --git a/apps/app_fax.c b/apps/app_fax.c
index bd6bdf9f6..e2b7a90ee 100644
--- a/apps/app_fax.c
+++ b/apps/app_fax.c
@@ -710,6 +710,7 @@ static int sndfax_exec(struct ast_channel *chan, const char *data)
int res = 0;
char *parse;
fax_session session;
+ char restore_digit_detect = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(file_name);
@@ -744,8 +745,32 @@ static int sndfax_exec(struct ast_channel *chan, const char *data)
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 @@ static int rcvfax_exec(struct ast_channel *chan, const char *data)
int res = 0;
char *parse;
fax_session session;
+ char restore_digit_detect = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(file_name);
@@ -788,8 +814,32 @@ static int rcvfax_exec(struct ast_channel *chan, const char *data)
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;
}
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 3567aa9e9..bd11e51ea 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -1507,6 +1507,7 @@ static struct ast_frame *dahdi_exception(struct ast_channel *ast);
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 @@ static const struct ast_channel_tech dahdi_tech = {
.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 @@ static int dahdi_answer(struct ast_channel *ast)
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 @@ static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int
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;
}
@@ -6279,39 +6364,6 @@ static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *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)
{
struct ast_channel *who;
@@ -6814,6 +6866,10 @@ static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_fra
}
}
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);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 4158ba5d4..4fd774b94 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1833,7 +1833,7 @@ struct sip_pvt {
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 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittyp
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 @@ static int sip_queryoption(struct ast_channel *chan, int option, void *data, int
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:
@@ -4135,6 +4177,11 @@ static int sip_queryoption(struct ast_channel *chan, int option, void *data, int
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 @@ static const char *hangup_cause2sip(int cause)
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 @@ static int sip_hangup(struct ast_channel *ast)
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 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
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 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
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 @@ static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p
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 @@ static int sip_dtmfmode(struct ast_channel *chan, const char *data)
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);
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index 46500d2e9..8b79a5e99 100644
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -400,6 +400,12 @@ enum ast_control_transfer {
/*! 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;