[asterisk-commits] irroot: branch irroot/distrotech-customers-trunk r326206 - /team/irroot/distr...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sun Jul 3 09:15:43 CDT 2011
Author: irroot
Date: Sun Jul 3 09:15:39 2011
New Revision: 326206
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=326206
Log:
Modify WaitFAX to use fax datastore to store status.
Allow setting tone played on channel while waiting.
Better error reporting
Modified:
team/irroot/distrotech-customers-trunk/res/res_fax.c
Modified: team/irroot/distrotech-customers-trunk/res/res_fax.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/distrotech-customers-trunk/res/res_fax.c?view=diff&rev=326206&r1=326205&r2=326206
==============================================================================
--- team/irroot/distrotech-customers-trunk/res/res_fax.c (original)
+++ team/irroot/distrotech-customers-trunk/res/res_fax.c Sun Jul 3 09:15:39 2011
@@ -229,10 +229,15 @@
<parameter name="timeout" required="true">
<para>Specifies the number of seconds we attempt to detect a fax tone on the channel</para>
</parameter>
+ <parameter name="tone" required="false">
+ <para>Either the tone name defined in the "indications.conf" configuration file,
+ or a directly specified list of frequencies and durations.</para>
+ <para>If not specified silence is generated.</para>
+ </parameter>
</syntax>
<description>
- <para>This application sets the following channel variable upon completion</para>
- <para> FAXDETECTED : 0 | 1</para>
+ <para>This application sets FAXOPT(status) To SUCCESS | FAILURE | ERROR</para>
+ <para>FAXOPT(statusstr) will be set to CNG | T38 on SUCCESS or reason on FAILURE | ERROR</para>
</description>
</application>
***/
@@ -3008,59 +3013,45 @@
return gateway->framehook;
}
-/*! \brief Alternate wait app that listens for CNG
- * \details This app answers the channel and waits for CNG tone
- * if the channel driver supports faxdetect it will proceed to the fax
- * extension.
- * it will return FAXDETECTED = 0 | 1 to allow dialplan processing where
- * the channel does not have fax detect or the Dialplan needs to handle faxdetection*/
-static int waitfax_exec(struct ast_channel *chan, const char *data)
-{
- char *parse;
- int timeout, tone = 0;
+/*! \brief Faxdetect loop used by WaitFAX
+ * \details Run DSP faxdetect on the channel for timeout seconds or until fax is detected
+ * \param chan channel to run fax detect on
+ * \param timeout maximum time to wait for fax detection
+ * \return 0 if nothing was detected 1 on CNG detected 2 if T38 negotiation is started -1 on error*/
+static int do_waitfax_exec(struct ast_channel *chan, int timeout)
+{
+ int timeleft = timeout;
+ int res = 0;
struct ast_dsp *dsp = NULL;
struct ast_frame *f;
enum ast_t38_state t38state = T38_STATE_UNKNOWN;
- struct ast_silence_generator *silgen = NULL;
struct ast_format orig_read_format;
AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(timeout);
- );
-
- parse = ast_strdupa(data);
- AST_STANDARD_APP_ARGS(args, parse);
-
- if (args.timeout) {
- timeout = atoi(args.timeout) * 1000;
- } else {
- pbx_builtin_setvar_helper(chan, "FAXDETECTED", "0");
- return 0;
- }
-
- if (chan->_state != AST_STATE_UP)
- ast_answer(chan);
-
/* Setup DSP CNG processing */
ast_format_copy(&orig_read_format, &chan->readformat);
- if (!ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
- if ((dsp=ast_dsp_new())) {
- ast_dsp_set_features(dsp, DSP_FEATURE_FAX_DETECT);
- ast_dsp_set_faxmode(dsp, DSP_FAXMODE_DETECT_CNG);
- }
+ switch (chan->readformat.id) {
+ case AST_FORMAT_SLINEAR:
+ case AST_FORMAT_ALAW:
+ case AST_FORMAT_ULAW:
+ break;
+ default:
+ if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ return -1;
+ }
+ }
+
+ if ((dsp = ast_dsp_new())) {
+ ast_dsp_set_features(dsp, DSP_FEATURE_FAX_DETECT);
+ ast_dsp_set_faxmode(dsp, DSP_FAXMODE_DETECT_CNG);
+ } else {
+ return -1;
}
AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
- /* If no other generator is present, start silencegen while waiting */
- if (ast_opt_transmit_silence && !chan->generatordata) {
- silgen = ast_channel_start_silence_generator(chan);
- }
-
- while ((timeout = ast_waitfor(chan, timeout))) {
- if (!(f=ast_read(chan))) {
- pbx_builtin_setvar_helper(chan, "FAXDETECTED", "0");
+ while ((timeleft = ast_waitfor(chan, timeleft))) {
+ if (!(f = ast_read(chan))) {
break;
}
@@ -3068,7 +3059,7 @@
(f->subclass.format.id == AST_FORMAT_ULAW) || (f->subclass.format.id == AST_FORMAT_ALAW))) {
f = ast_dsp_process(chan, dsp, f);
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass.integer == 'f')) {
- tone=1;
+ res = 1;
ast_dsp_free(dsp);
dsp = NULL;
}
@@ -3081,22 +3072,15 @@
}
t38state = ast_channel_get_t38_state(chan);
- if ((t38state == T38_STATE_NEGOTIATING) || (t38state == T38_STATE_NEGOTIATED) || tone) {
- pbx_builtin_setvar_helper(chan, "FAXDETECTED", "1");
+ if ((t38state == T38_STATE_NEGOTIATING) || (t38state == T38_STATE_NEGOTIATED)) {
+ res = 2;
break;
- }
- }
-
- if (timeout <= 0) {
- pbx_builtin_setvar_helper(chan, "FAXDETECTED", "0");
- }
-
- /* stop silgen if present */
- if (silgen) {
- ast_channel_stop_silence_generator(chan, silgen);
- }
-
- if (orig_read_format.id) {
+ } else if (res) {
+ break;
+ }
+ }
+
+ if (orig_read_format.id != chan->readformat.id) {
ast_set_read_format(chan, &orig_read_format);
}
@@ -3110,8 +3094,102 @@
ast_dsp_free(dsp);
}
+ return res;
+}
+
+/*! \brief Alternate wait app that listens for CNG
+ * \details This app answers the channel and waits for CNG tone or T38 negotiation
+ * if the channel driver supports faxdetect it will proceed to the fax
+ * extension.
+ * it will set FAXOPT(status) and FAXOPT(statusstr) allowing dial plan processing where
+ * the channel does not have fax detect or the Dialplan needs to handle faxdetection
+ *
+ * \param chan channel this application is called on
+ * \param data the paramaters passed to the application
+ * \return this application will always return 0
+ */
+static int waitfax_exec(struct ast_channel *chan, const char *data)
+{
+ int res = 0;
+ int timeout = 0;
+ int ptres = -1;
+ char *parse;
+ struct ast_fax_session_details *details;
+ struct ast_silence_generator *silgen = NULL;
+ struct ast_tone_zone_sound *ts;
+
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(timeout);
+ AST_APP_ARG(tone);
+ );
+
+ if (!(details = find_or_create_details(chan))) {
+ ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
+ return 0;
+ }
+
+ parse = ast_strdupa(data);
+ AST_STANDARD_APP_ARGS(args, parse);
+
+ if (args.timeout) {
+ timeout = atoi(args.timeout) * 1000;
+ }
+
+ if (timeout <= 0) {
+ ast_string_field_set(details, result, "ERROR");
+ ast_string_field_set(details, resultstr, "Invalid timeout in WaitFAX");
+ ast_log(LOG_ERROR, "Application WaitFAX requires a valid timeout\n");
+ ao2_ref(details, -1);
+ return 0;
+ }
+
+ if (chan->_state != AST_STATE_UP) {
+ ast_answer(chan);
+ }
+
+ /* If no other generator is present, start tone or silencegen while waiting */
+ if (!chan->generatordata && !ast_strlen_zero(args.tone)) {
+ if ((ts = ast_get_indication_tone(chan->zone, args.tone))) {
+ ptres = ast_playtones_start(chan, 0, ts->data, 0);
+ ts = ast_tone_zone_sound_unref(ts);
+ } else {
+ ptres = ast_playtones_start(chan, 0, args.tone, 0);
+ }
+ if (!ptres && ast_opt_transmit_silence) {
+ silgen = ast_channel_start_silence_generator(chan);
+ }
+ } else if (ast_opt_transmit_silence && !chan->generatordata) {
+ silgen = ast_channel_start_silence_generator(chan);
+ }
+
+ res = do_waitfax_exec(chan, timeout);
+
+ /* stop silgen or tones if present */
+ if (silgen) {
+ ast_channel_stop_silence_generator(chan, silgen);
+ } else if (!ptres) {
+ ast_playtones_stop(chan);
+ }
+
+ if (res > 0) {
+ ast_string_field_set(details, result, "SUCCESS");
+ if (res == 1) {
+ ast_string_field_set(details, resultstr, "CNG");
+ } else {
+ ast_string_field_set(details, resultstr, "T38");
+ }
+ } else if (res < 0) {
+ ast_string_field_set(details, result, "ERROR");
+ ast_string_field_set(details, resultstr, "DSP Error WaitFAX Failed");
+ } else {
+ ast_string_field_set(details, result, "FAILED");
+ ast_string_field_set(details, resultstr, "No CNG Tone Or T38 Detected");
+ }
+
+ ao2_ref(details, -1);
return 0;
}
+
/*! \brief hash callback for ao2 */
static int session_hash_cb(const void *obj, const int flags)
More information about the asterisk-commits
mailing list