[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