[asterisk-commits] irroot: branch irroot/t38gateway-1.8 r339503 - /team/irroot/t38gateway-1.8/res/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Oct 5 02:32:26 CDT 2011
Author: irroot
Date: Wed Oct 5 02:32:23 2011
New Revision: 339503
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=339503
Log:
Fully backport res_fax from trunk
Modified:
team/irroot/t38gateway-1.8/res/res_fax.c
Modified: team/irroot/t38gateway-1.8/res/res_fax.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/res/res_fax.c?view=diff&rev=339503&r1=339502&r2=339503
==============================================================================
--- team/irroot/t38gateway-1.8/res/res_fax.c (original)
+++ team/irroot/t38gateway-1.8/res/res_fax.c Wed Oct 5 02:32:23 2011
@@ -98,6 +98,9 @@
<option name="f">
<para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
</option>
+ <option name="F">
+ <para>Force usage of audio mode on T.38 capable channels.</para>
+ </option>
<option name="s">
<para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
</option>
@@ -130,6 +133,9 @@
</option>
<option name="f">
<para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
+ </option>
+ <option name="F">
+ <para>Force usage of audio mode on T.38 capable channels.</para>
</option>
<option name="s">
<para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
@@ -187,7 +193,7 @@
<para>R/W T38 fax gateway, with optional fax activity timeout in seconds (yes[,timeout]/no)</para>
</enum>
<enum name="faxdetect">
- <para>R/W Enable FAX detect with optional timeout in seconds (yes[,timeout]/no)</para>
+ <para>R/W Enable FAX detect with optional timeout in seconds (yes,t38,cng[,timeout]/no)</para>
</enum>
<enum name="pages">
<para>R/O Number of pages transferred.</para>
@@ -275,13 +281,16 @@
struct ast_dsp *dsp;
/*! \brief original audio formats */
unsigned int orig_format;
- /*! \brief Noise limit to end faxdetect */
- int noiselim;
- /*! \brief result of the framehook e[CED]/f[CNG]/n[Noise]/t[T38] */
- int result;
/*! \brief fax session details */
struct ast_fax_session_details *details;
+ /*! \brief mode */
+ int flags;
};
+
+/*! \brief FAX Detect flags */
+#define FAX_DETECT_MODE_CNG (1 << 0)
+#define FAX_DETECT_MODE_T38 (1 << 1)
+#define FAX_DETECT_MODE_BOTH (FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38)
static int fax_logger_level = -1;
@@ -342,6 +351,7 @@
OPT_STATUS = (1 << 3),
OPT_ALLOWAUDIO = (1 << 5),
OPT_REQUEST_T38 = (1 << 6),
+ OPT_FORCE_AUDIO = (1 << 7),
};
AST_APP_OPTIONS(fax_exec_options, BEGIN_OPTIONS
@@ -349,6 +359,7 @@
AST_APP_OPTION('c', OPT_CALLERMODE),
AST_APP_OPTION('d', OPT_DEBUG),
AST_APP_OPTION('f', OPT_ALLOWAUDIO),
+ AST_APP_OPTION('F', OPT_FORCE_AUDIO),
AST_APP_OPTION('s', OPT_STATUS),
AST_APP_OPTION('z', OPT_REQUEST_T38),
END_OPTIONS);
@@ -577,7 +588,6 @@
}
return 0;
}
-
static char *ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
{
char *out = buf;
@@ -623,9 +633,10 @@
if (!first) {
ast_build_string(&buf, &size, ",");
}
- ast_build_string(&buf, &size, "T38_GATEWAY");
+ ast_build_string(&buf, &size, "GATEWAY");
first = 0;
}
+
return out;
}
@@ -840,6 +851,9 @@
}
if (s->details) {
+ if (s->details->caps & AST_FAX_TECH_GATEWAY) {
+ s->details->caps &= ~AST_FAX_TECH_GATEWAY;
+ }
ao2_ref(s->details, -1);
}
@@ -877,7 +891,6 @@
{
struct ast_fax_session *s;
struct fax_module *faxmod;
- char caps[128] = "";
if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
return NULL;
@@ -903,6 +916,7 @@
AST_RWLIST_UNLOCK(&faxmodules);
if (!faxmod) {
+ char caps[128] = "";
ast_log(LOG_ERROR, "Could not locate a FAX technology module with capabilities (%s)\n", ast_fax_caps_to_str(details->caps, caps, sizeof(caps)));
ao2_ref(s, -1);
return NULL;
@@ -944,7 +958,6 @@
{
struct ast_fax_session *s = NULL;
struct fax_module *faxmod;
- char caps[128] = "";
if (reserved) {
s = reserved;
@@ -1020,6 +1033,7 @@
AST_RWLIST_UNLOCK(&faxmodules);
if (!faxmod) {
+ char caps[128] = "";
ast_log(LOG_ERROR, "Could not locate a FAX technology module with capabilities (%s)\n", ast_fax_caps_to_str(details->caps, caps, sizeof(caps)));
ao2_ref(s, -1);
return NULL;
@@ -1498,10 +1512,9 @@
set_channel_variables(chan, details);
+ ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
if (!strcasecmp(details->result, "FAILED")) {
ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
- } else {
- ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
}
if (fax) {
@@ -1702,14 +1715,9 @@
pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
- /* if we ran receivefax then we attempted to receive a fax, even if we
- * never start a fax session */
- ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
-
/* Get a FAX session details structure from the channel's FAX datastore and create one if
* it does not already exist. */
if (!(details = find_or_create_details(chan))) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
@@ -1721,7 +1729,7 @@
ast_string_field_set(details, error, "INIT_ERROR");
set_channel_variables(chan, details);
- if ((details->caps & AST_FAX_TECH_GATEWAY) && (details->gateway_id > 0)) {
+ if (details->gateway_id > 0) {
ast_string_field_set(details, resultstr, "can't receive a fax on a channel with a T.38 gateway");
set_channel_variables(chan, details);
ast_log(LOG_ERROR, "executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
@@ -1730,7 +1738,6 @@
}
if (details->maxrate < details->minrate) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
ast_string_field_set(details, resultstr, "maxrate is less than minrate");
set_channel_variables(chan, details);
@@ -1740,7 +1747,6 @@
}
if (check_modem_rate(details->modems, details->minrate)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
@@ -1751,7 +1757,6 @@
}
if (check_modem_rate(details->modems, details->maxrate)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
@@ -1762,7 +1767,6 @@
}
if (ast_strlen_zero(data)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
ast_string_field_set(details, resultstr, "invalid arguments");
set_channel_variables(chan, details);
@@ -1775,7 +1779,6 @@
if (!ast_strlen_zero(args.options) &&
ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
ast_string_field_set(details, resultstr, "invalid arguments");
set_channel_variables(chan, details);
@@ -1783,7 +1786,6 @@
return -1;
}
if (ast_strlen_zero(args.filename)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
ast_string_field_set(details, resultstr, "invalid arguments");
set_channel_variables(chan, details);
@@ -1794,7 +1796,6 @@
/* check for unsupported FAX application options */
if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
ast_string_field_set(details, resultstr, "invalid arguments");
set_channel_variables(chan, details);
@@ -1802,12 +1803,13 @@
ao2_ref(details, -1);
return -1;
}
+
+ ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "MEMORY_ERROR");
ast_string_field_set(details, resultstr, "error allocating memory");
set_channel_variables(chan, details);
@@ -1835,12 +1837,12 @@
t38state = ast_channel_get_t38_state(chan);
if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
- ast_test_flag(&opts, OPT_ALLOWAUDIO)) {
+ ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
+ ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
}
if (!(s = fax_session_reserve(details, &token))) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, resultstr, "error reserving fax session");
set_channel_variables(chan, details);
ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
@@ -1851,7 +1853,6 @@
/* make sure the channel is up */
if (chan->_state != AST_STATE_UP) {
if (ast_answer(chan)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, resultstr, "error answering channel");
set_channel_variables(chan, details);
ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
@@ -1862,20 +1863,22 @@
}
}
- if (set_fax_t38_caps(chan, details)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
- ast_string_field_set(details, error, "T38_NEG_ERROR");
- ast_string_field_set(details, resultstr, "error negotiating T.38");
- set_channel_variables(chan, details);
- fax_session_release(s, token);
- ao2_ref(s, -1);
- ao2_ref(details, -1);
- return -1;
- }
-
- if (details->caps & AST_FAX_TECH_T38) {
+ if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
+ if (set_fax_t38_caps(chan, details)) {
+ ast_string_field_set(details, error, "T38_NEG_ERROR");
+ ast_string_field_set(details, resultstr, "error negotiating T.38");
+ set_channel_variables(chan, details);
+ fax_session_release(s, token);
+ ao2_ref(s, -1);
+ ao2_ref(details, -1);
+ return -1;
+ }
+ } else {
+ details->caps |= AST_FAX_TECH_AUDIO;
+ }
+
+ if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
if (receivefax_t38_init(chan, details)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "T38_NEG_ERROR");
ast_string_field_set(details, resultstr, "error negotiating T.38");
set_channel_variables(chan, details);
@@ -2182,14 +2185,9 @@
pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
- /* if we ran sendfax then we attempted to send a fax, even if we never
- * start a fax session */
- ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
-
/* Get a requirement structure and set it. This structure is used
* to tell the FAX technology module about the higher level FAX session */
if (!(details = find_or_create_details(chan))) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
@@ -2201,7 +2199,7 @@
ast_string_field_set(details, error, "INIT_ERROR");
set_channel_variables(chan, details);
- if ((details->caps & AST_FAX_TECH_GATEWAY) && (details->gateway_id > 0)) {
+ if (details->gateway_id > 0) {
ast_string_field_set(details, resultstr, "can't send a fax on a channel with a T.38 gateway");
set_channel_variables(chan, details);
ast_log(LOG_ERROR, "executing SendFAX on a channel with a T.38 Gateway is not supported\n");
@@ -2210,7 +2208,6 @@
}
if (details->maxrate < details->minrate) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
ast_string_field_set(details, resultstr, "maxrate is less than minrate");
set_channel_variables(chan, details);
@@ -2220,7 +2217,6 @@
}
if (check_modem_rate(details->modems, details->minrate)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
@@ -2231,7 +2227,6 @@
}
if (check_modem_rate(details->modems, details->maxrate)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
@@ -2242,7 +2237,6 @@
}
if (ast_strlen_zero(data)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
ast_string_field_set(details, resultstr, "invalid arguments");
set_channel_variables(chan, details);
@@ -2256,7 +2250,6 @@
if (!ast_strlen_zero(args.options) &&
ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
ast_string_field_set(details, resultstr, "invalid arguments");
set_channel_variables(chan, details);
@@ -2264,7 +2257,6 @@
return -1;
}
if (ast_strlen_zero(args.filenames)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
ast_string_field_set(details, resultstr, "invalid arguments");
set_channel_variables(chan, details);
@@ -2275,7 +2267,6 @@
/* check for unsupported FAX application options */
if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "INVALID_ARGUMENTS");
ast_string_field_set(details, resultstr, "invalid arguments");
set_channel_variables(chan, details);
@@ -2284,11 +2275,12 @@
return -1;
}
+ ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
+
file_count = 0;
filenames = args.filenames;
while ((c = strsep(&filenames, "&"))) {
if (access(c, (F_OK | R_OK)) < 0) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "FILE_ERROR");
ast_string_field_set(details, resultstr, "error reading file");
set_channel_variables(chan, details);
@@ -2298,7 +2290,6 @@
}
if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "MEMORY_ERROR");
ast_string_field_set(details, resultstr, "error allocating memory");
set_channel_variables(chan, details);
@@ -2312,10 +2303,6 @@
file_count++;
}
- if (file_count > 1) {
- details->caps |= AST_FAX_TECH_MULTI_DOC;
- }
-
ast_verb(3, "Channel '%s' sending FAX:\n", chan->name);
AST_LIST_TRAVERSE(&details->documents, doc, next) {
ast_verb(3, " %s\n", doc->filename);
@@ -2323,6 +2310,10 @@
details->caps = AST_FAX_TECH_SEND;
+ if (file_count > 1) {
+ details->caps |= AST_FAX_TECH_MULTI_DOC;
+ }
+
/* check for debug */
if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
details->option.debug = AST_FAX_OPTFLAG_TRUE;
@@ -2335,7 +2326,8 @@
t38state = ast_channel_get_t38_state(chan);
if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
- ast_test_flag(&opts, OPT_ALLOWAUDIO)) {
+ ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
+ ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
}
@@ -2344,7 +2336,6 @@
}
if (!(s = fax_session_reserve(details, &token))) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, resultstr, "error reserving fax session");
set_channel_variables(chan, details);
ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
@@ -2355,7 +2346,6 @@
/* make sure the channel is up */
if (chan->_state != AST_STATE_UP) {
if (ast_answer(chan)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, resultstr, "error answering channel");
set_channel_variables(chan, details);
ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
@@ -2366,20 +2356,22 @@
}
}
- if (set_fax_t38_caps(chan, details)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
- ast_string_field_set(details, error, "T38_NEG_ERROR");
- ast_string_field_set(details, resultstr, "error negotiating T.38");
- set_channel_variables(chan, details);
- fax_session_release(s, token);
- ao2_ref(s, -1);
- ao2_ref(details, -1);
- return -1;
- }
-
- if (details->caps & AST_FAX_TECH_T38) {
+ if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
+ if (set_fax_t38_caps(chan, details)) {
+ ast_string_field_set(details, error, "T38_NEG_ERROR");
+ ast_string_field_set(details, resultstr, "error negotiating T.38");
+ set_channel_variables(chan, details);
+ fax_session_release(s, token);
+ ao2_ref(s, -1);
+ ao2_ref(details, -1);
+ return -1;
+ }
+ } else {
+ details->caps |= AST_FAX_TECH_AUDIO;
+ }
+
+ if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
if (sendfax_t38_init(chan, details)) {
- ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, error, "T38_NEG_ERROR");
ast_string_field_set(details, resultstr, "error negotiating T.38");
set_channel_variables(chan, details);
@@ -2464,7 +2456,6 @@
if (gateway->s) {
fax_session_release(gateway->s, gateway->token);
gateway->token = NULL;
- gateway->s->details->caps |= ~AST_FAX_TECH_GATEWAY;
ao2_lock(faxregistry.container);
ao2_unlink(faxregistry.container, gateway->s);
@@ -2508,7 +2499,7 @@
details->caps = AST_FAX_TECH_GATEWAY;
if (details->gateway_timeout && !(gateway->s = fax_session_reserve(details, &gateway->token))) {
- details->caps |= ~AST_FAX_TECH_GATEWAY;
+ details->caps &= ~AST_FAX_TECH_GATEWAY;
ast_log(LOG_ERROR, "Can't reserve a FAX session, gateway attempt failed.\n");
ao2_ref(gateway, -1);
return NULL;
@@ -3170,19 +3161,17 @@
/*! \brief Create a new fax detect object.
* \param chan the channel attaching to
* \param timeout remove framehook in this time if set
- * \param noiselim end faxdetect when noiselim ms of noise is detected
- * \param dsp_detect_flag dsp faxmode detect flags
+ * \param flags required options
* \return NULL or a fax gateway object
*/
-static struct fax_detect *fax_detect_new(struct ast_channel *chan, int timeout, int noiselim, int dsp_detect_flag)
+static struct fax_detect *fax_detect_new(struct ast_channel *chan, int timeout, int flags)
{
struct fax_detect *faxdetect = ao2_alloc(sizeof(*faxdetect), destroy_faxdetect);
if (!faxdetect) {
return NULL;
}
- faxdetect->noiselim = noiselim;
- faxdetect->result = 0;
+ faxdetect->flags = flags;
if (timeout) {
faxdetect->timeout_start = ast_tvnow();
@@ -3191,15 +3180,18 @@
faxdetect->timeout_start.tv_usec = 0;
}
- faxdetect->dsp = ast_dsp_new();
- if (!faxdetect->dsp) {
- ao2_ref(faxdetect, -1);
- return NULL;
- }
-
- ast_dsp_set_features(faxdetect->dsp, DSP_FEATURE_FAX_DETECT);
- ast_dsp_set_faxmode(faxdetect->dsp, dsp_detect_flag || DSP_FAXMODE_DETECT_SQUELCH);
- ast_dsp_set_threshold(faxdetect->dsp, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
+ if (faxdetect->flags & FAX_DETECT_MODE_CNG) {
+ faxdetect->dsp = ast_dsp_new();
+ if (!faxdetect->dsp) {
+ ao2_ref(faxdetect, -1);
+ return NULL;
+ }
+ ast_dsp_set_features(faxdetect->dsp, DSP_FEATURE_FAX_DETECT);
+ ast_dsp_set_faxmode(faxdetect->dsp, DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_SQUELCH);
+ } else {
+ faxdetect->dsp = NULL;
+ }
+
return faxdetect;
}
@@ -3227,7 +3219,7 @@
struct ast_fax_session_details *details;
struct ast_control_t38_parameters *control_params;
struct ast_channel *peer;
- int dspnoise;
+ int result = 0;
details = faxdetect->details;
@@ -3272,9 +3264,13 @@
return f;
}
- /* only handle VOICE/DTMF and CONTROL frames*/
+ /* only handle VOICE and CONTROL frames*/
switch (f->frametype) {
case AST_FRAME_VOICE:
+ /* we have no DSP this means we not detecting CNG */
+ if (!faxdetect->dsp) {
+ break;
+ }
/* We can only process some formats*/
switch (f->subclass.codec) {
case AST_FORMAT_SLINEAR:
@@ -3284,12 +3280,8 @@
}
break;
case AST_FRAME_CONTROL:
- if (f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
- break;
- }
- return f;
- case AST_FRAME_DTMF:
- if ((f->subclass.integer == 'f') || (f->subclass.integer == 'e')) {
+ if ((f->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
+ (faxdetect->flags & FAX_DETECT_MODE_T38)) {
break;
}
return f;
@@ -3300,30 +3292,23 @@
if (f->frametype == AST_FRAME_VOICE) {
f = ast_dsp_process(chan, faxdetect->dsp, f);
if (f->frametype == AST_FRAME_DTMF) {
- faxdetect->result = f->subclass.integer;
- } else if ((f->frametype == AST_FRAME_VOICE) && (faxdetect->noiselim > 0)) {
- ast_dsp_noise(faxdetect->dsp, f, &dspnoise);
- if (dspnoise > faxdetect->noiselim) {
- faxdetect->result = 'n';
- }
+ result = f->subclass.integer;
}
} else if ((f->frametype == AST_FRAME_CONTROL) && (f->datalen == sizeof(struct ast_control_t38_parameters))) {
control_params = f->data.ptr;
switch (control_params->request_response) {
case AST_T38_NEGOTIATED:
case AST_T38_REQUEST_NEGOTIATE:
- faxdetect->result = 't';
+ result = 't';
break;
default:
break;
}
- } else if (f->frametype == AST_FRAME_DTMF) {
- faxdetect->result = f->subclass.integer;
- }
-
- if (faxdetect->result) {
+ }
+
+ if (result) {
const char *target_context = S_OR(chan->macrocontext, chan->context);
- switch (faxdetect->result) {
+ switch (result) {
case 'f':
case 't':
ast_channel_unlock(chan);
@@ -3331,7 +3316,7 @@
S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
ast_channel_lock(chan);
ast_verbose(VERBOSE_PREFIX_2 "Redirecting '%s' to fax extension due to %s detection\n",
- chan->name, (faxdetect->result == 'f') ? "CNG" : "T38");
+ chan->name, (result == 'f') ? "CNG" : "T38");
pbx_builtin_setvar_helper(chan, "FAXEXTEN", chan->exten);
if (ast_async_goto(chan, target_context, "fax", 1)) {
ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", chan->name, target_context);
@@ -3340,8 +3325,8 @@
f = &ast_null_frame;
} else {
ast_channel_lock(chan);
- ast_log(LOG_NOTICE, "FAX %s detected but no fax extension\n",
- (faxdetect->result == 'f') ? "CNG" : "T38");
+ ast_log(LOG_NOTICE, "FAX %s detected but no fax extension in context (%s)\n",
+ (result == 'f') ? "CNG" : "T38", target_context);
}
}
ast_framehook_detach(chan, details->faxdetect_id);
@@ -3354,12 +3339,11 @@
/*! \brief Attach a faxdetect framehook object to a channel.
* \param chan the channel to attach to
* \param timeout remove framehook in this time if set
- * \param noiselim end faxdetect when noiselim ms of noise is detected
- * \param dsp_detect_flag dsp faxmode detect flags
* \return the faxdetect structure or NULL on error
+ * \param flags required options
* \retval -1 error
*/
-static struct fax_detect* fax_detect_attach(struct ast_channel *chan, int timeout, int noiselim, int dsp_detect_flags)
+static int fax_detect_attach(struct ast_channel *chan, int timeout, int flags)
{
struct fax_detect *faxdetect;
struct ast_fax_session_details *details;
@@ -3371,14 +3355,14 @@
if (!(details = find_or_create_details(chan))) {
ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
- return NULL;
+ return -1;
}
/* set up the frame hook*/
- faxdetect = fax_detect_new(chan, timeout, noiselim, dsp_detect_flags);
+ faxdetect = fax_detect_new(chan, timeout, flags);
if (!faxdetect) {
ao2_ref(details, -1);
- return NULL;
+ return -1;
}
fr_hook.data = faxdetect;
@@ -3388,14 +3372,10 @@
ast_channel_unlock(chan);
if (details->faxdetect_id < 0) {
- ao2_ref(details, -1);
ao2_ref(faxdetect, -1);
- return NULL;
- }
-
- /* return it with ref held in framhook and return*/
- ao2_ref(faxdetect, 1);
- return faxdetect;
+ }
+
+ return details->faxdetect_id;
}
/*! \brief hash callback for ao2 */
@@ -3916,27 +3896,38 @@
const char *val = ast_skip_blanks(value);
char *timeout = strchr(val, ',');
unsigned int fdtimeout = 0;
- struct fax_detect *faxdetect;
+ int flags;
+ int faxdetect;
if (timeout) {
*timeout++ = '\0';
}
- if (ast_true(val)) {
+ if (ast_true(val) || !strcasecmp(val, "t38") || !strcasecmp(val, "cng")) {
if (details->faxdetect_id < 0) {
if (timeout && (sscanf(timeout, "%u", &fdtimeout) == 1)) {
- fdtimeout = fdtimeout * 1000;
+ if (fdtimeout > 0) {
+ fdtimeout = fdtimeout * 1000;
+ } else {
+ ast_log(LOG_WARNING, "Timeout cannot be negative ignoring timeout\n");
+ }
}
- faxdetect = fax_detect_attach(chan, fdtimeout, 0, DSP_FAXMODE_DETECT_CNG);
-
- if (faxdetect && (details->faxdetect_id >= 0)) {
- ast_debug(1, "Attached FAX detect to channel %s.\n", chan->name);
+ if (!strcasecmp(val, "t38")) {
+ flags = FAX_DETECT_MODE_T38;
+ } else if (!strcasecmp(val, "cng")) {
+ flags = FAX_DETECT_MODE_CNG;
} else {
+ flags = FAX_DETECT_MODE_BOTH;
+ }
+
+ faxdetect = fax_detect_attach(chan, fdtimeout, flags);
+ if (faxdetect < 0) {
ast_log(LOG_ERROR, "Error attaching FAX detect to channel %s.\n", chan->name);
res = -1;
+ } else {
+ ast_debug(1, "Attached FAX detect to channel %s.\n", chan->name);
}
- ao2_ref(faxdetect, -1);
} else {
ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", chan->name);
}
More information about the asterisk-commits
mailing list