[asterisk-commits] irroot: branch irroot/distrotech-customers-10 r333483 - /team/irroot/distrote...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sat Aug 27 03:20:26 CDT 2011
Author: irroot
Date: Sat Aug 27 03:20:23 2011
New Revision: 333483
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=333483
Log:
WaitFAX application in res_fax RB1116
Modified:
team/irroot/distrotech-customers-10/res/res_fax.c
Modified: team/irroot/distrotech-customers-10/res/res_fax.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/distrotech-customers-10/res/res_fax.c?view=diff&rev=333483&r1=333482&r2=333483
==============================================================================
--- team/irroot/distrotech-customers-10/res/res_fax.c (original)
+++ team/irroot/distrotech-customers-10/res/res_fax.c Sat Aug 27 03:20:23 2011
@@ -228,10 +228,33 @@
<ref type="application">SendFax</ref>
</see-also>
</function>
+ <application name="WaitFAX" language="en_US">
+ <synopsis>
+ Generic Fax Detect CNG/T.38 (Wait For Fax)
+ </synopsis>
+ <syntax>
+ <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>
+ <parameter name="noise" required="false">
+ <para>Number of ms noise detected before proceeding with the dialplan.</para>
+ </parameter>
+ </syntax>
+ <description>
+ <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>
***/
static const char app_receivefax[] = "ReceiveFAX";
static const char app_sendfax[] = "SendFAX";
+static const char app_waitfax[] = "WaitFAX";
struct debug_info_history {
unsigned int consec_frames;
@@ -3066,6 +3089,197 @@
return gateway->framehook;
}
+/*! \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 noiselim)
+{
+ int timeleft = timeout;
+ int res = 0;
+ int dspnoise = 0;
+ struct ast_dsp *dsp = NULL;
+ struct ast_frame *f;
+ enum ast_t38_state t38state = T38_STATE_UNKNOWN;
+ struct ast_format orig_read_format;
+ AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
+
+ /* Setup DSP CNG processing */
+ ast_format_copy(&orig_read_format, &chan->readformat);
+ 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 | DSP_FAXMODE_DETECT_SQUELCH);
+ ast_dsp_set_threshold(dsp, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
+ } else {
+ return -1;
+ }
+
+ AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
+
+ while ((timeleft = ast_waitfor(chan, timeleft))) {
+ if (!(f = ast_read(chan))) {
+ break;
+ }
+
+ if (dsp && (f->frametype == AST_FRAME_VOICE) && ((f->subclass.format.id == AST_FORMAT_SLINEAR) ||
+ (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')) {
+ res = 1;
+ } else if ((f->frametype == AST_FRAME_VOICE) && (noiselim > 0)) {
+ ast_dsp_noise(dsp, f, &dspnoise);
+ if (dspnoise > noiselim) {
+ break;
+ }
+ }
+ }
+
+ if (ast_is_deferrable_frame(f)) {
+ AST_LIST_INSERT_HEAD(&deferred_frames, f, frame_list);
+ } else {
+ ast_frfree(f);
+ }
+
+ t38state = ast_channel_get_t38_state(chan);
+ if ((t38state == T38_STATE_NEGOTIATING) || (t38state == T38_STATE_NEGOTIATED)) {
+ res = 2;
+ break;
+ } else if (res) {
+ break;
+ }
+ }
+
+ if (orig_read_format.id != chan->readformat.id) {
+ ast_set_read_format(chan, &orig_read_format);
+ }
+
+ ast_channel_lock(chan);
+ while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) {
+ ast_queue_frame_head(chan, ast_frisolate(f));
+ }
+ ast_channel_unlock(chan);
+
+ if (dsp) {
+ 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;
+ unsigned int timeout;
+ unsigned int noiselim;
+ 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);
+ AST_APP_ARG(noise);
+ );
+
+ 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 (!ast_strlen_zero(args.timeout) && sscanf(args.timeout, "%u", &timeout) == 1) {
+ timeout = timeout * 1000;
+ } else {
+ timeout = 0;
+ }
+
+ 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 (ast_strlen_zero(args.noise) || sscanf(args.noise, "%u", &noiselim) != 1) {
+ noiselim = 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, noiselim);
+
+ /* 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)
{
@@ -3626,6 +3840,10 @@
ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
}
+ if (ast_unregister_application(app_waitfax) < 0) {
+ ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_waitfax);
+ }
+
if (fax_logger_level != -1) {
ast_logger_unregister_level("FAX");
}
@@ -3666,8 +3884,12 @@
return AST_MODULE_LOAD_DECLINE;
}
+ if (ast_register_application_xml(app_waitfax, waitfax_exec) < 0) {
+ ast_log(LOG_WARNING, "failed to register '%s'.\n", app_waitfax);
+ }
+
ast_cli_register_multiple(fax_cli, ARRAY_LEN(fax_cli));
- res = ast_custom_function_register(&acf_faxopt);
+ res = ast_custom_function_register(&acf_faxopt);
fax_logger_level = ast_logger_register_level("FAX");
return res;
More information about the asterisk-commits
mailing list