Fri Jun 19 12:09:30 2009

Asterisk developer's documentation


app_waitforsilence.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * WaitForSilence Application by David C. Troy <dave@popvox.com>
00007  * Version 1.11 2006-06-29
00008  *
00009  * Mark Spencer <markster@digium.com>
00010  *
00011  * See http://www.asterisk.org for more information about
00012  * the Asterisk project. Please do not directly contact
00013  * any of the maintainers of this project for assistance;
00014  * the project provides a web site, mailing lists and IRC
00015  * channels for your use.
00016  *
00017  * This program is free software, distributed under the terms of
00018  * the GNU General Public License Version 2. See the LICENSE file
00019  * at the top of the source tree.
00020  */
00021 
00022 /*! \file
00023  *
00024  * \brief Wait for Silence
00025  *   - Waits for up to 'x' milliseconds of silence, 'y' times \n
00026  *   - WaitForSilence(500,2) will wait for 1/2 second of silence, twice \n
00027  *   - WaitForSilence(1000,1) will wait for 1 second of silence, once \n
00028  *   - WaitForSilence(300,3,10) will wait for 300ms of silence, 3 times, and return after 10sec \n
00029  *
00030  * \author David C. Troy <dave@popvox.com>
00031  *
00032  * \brief Wait For Noise
00033  * The same as Wait For Silence but listenes noise on the chennel that is above \n
00034  * the pre-configured silence threshold from dsp.conf
00035  *
00036  * \author Philipp Skadorov <skadorov@yahoo.com>
00037  *
00038  * \ingroup applications
00039  */
00040 
00041 #include "asterisk.h"
00042 
00043 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 174947 $")
00044 
00045 #include "asterisk/file.h"
00046 #include "asterisk/channel.h"
00047 #include "asterisk/pbx.h"
00048 #include "asterisk/dsp.h"
00049 #include "asterisk/module.h"
00050 
00051 static char *app_silence = "WaitForSilence";
00052 static char *synopsis_silence = "Waits for a specified amount of silence";
00053 static char *descrip_silence =
00054 "  WaitForSilence(silencerequired[,iterations][,timeout]):\n"
00055 "Wait for Silence: Waits for up to 'silencerequired' \n"
00056 "milliseconds of silence, 'iterations' times or once if omitted.\n"
00057 "An optional timeout specified the number of seconds to return\n"
00058 "after, even if we do not receive the specified amount of silence.\n"
00059 "Use 'timeout' with caution, as it may defeat the purpose of this\n"
00060 "application, which is to wait indefinitely until silence is detected\n"
00061 "on the line.  This is particularly useful for reverse-911-type\n"
00062 "call broadcast applications where you need to wait for an answering\n"
00063 "machine to complete its spiel before playing a message.\n"
00064 "The timeout parameter is specified only to avoid an infinite loop in\n"
00065 "cases where silence is never achieved.  Typically you will want to\n"
00066 "include two or more calls to WaitForSilence when dealing with an answering\n"
00067 "machine; first waiting for the spiel to finish, then waiting for the beep, etc.\n\n"
00068   "Examples:\n"
00069 "  - WaitForSilence(500,2) will wait for 1/2 second of silence, twice\n"
00070 "  - WaitForSilence(1000) will wait for 1 second of silence, once\n"
00071 "  - WaitForSilence(300,3,10) will wait for 300ms silence, 3 times,\n"
00072 "     and returns after 10 sec, even if silence is not detected\n\n"
00073 "Sets the channel variable WAITSTATUS with to one of these values:\n"
00074 "SILENCE - if exited with silence detected\n"
00075 "TIMEOUT - if exited without silence detected after timeout\n";
00076 
00077 static char *app_noise = "WaitForNoise";
00078 static char *synopsis_noise = "Waits for a specified amount of noise";
00079 static char *descrip_noise =
00080 "WaitForNoise(noiserequired[,iterations][,timeout]) \n"
00081 "Wait for Noise: The same as Wait for Silance but waits for noise that is above the threshold specified\n";
00082 
00083 static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int timeout, int wait_for_silence) {
00084    struct ast_frame *f = NULL;
00085    int dsptime = 0;
00086    int rfmt = 0;
00087    int res = 0;
00088    struct ast_dsp *sildet;  /* silence detector dsp */
00089    time_t now;
00090 
00091    /*Either silence or noise calc depending on wait_for_silence flag*/
00092    int (*ast_dsp_func)(struct ast_dsp*, struct ast_frame*, int*) =
00093             wait_for_silence ? ast_dsp_silence : ast_dsp_noise;
00094 
00095    rfmt = chan->readformat; /* Set to linear mode */
00096    if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
00097       ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n");
00098       return -1;
00099    }
00100 
00101    /* Create the silence detector */
00102    if (!(sildet = ast_dsp_new())) {
00103       ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00104       return -1;
00105    }
00106    ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
00107 
00108    /* Await silence... */
00109    for (;;) {
00110       /* Start with no silence received */
00111       dsptime = 0;
00112 
00113       res = ast_waitfor(chan, timereqd);
00114 
00115       /* Must have gotten a hangup; let's exit */
00116       if (res < 0) {
00117          pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
00118          break;
00119       }
00120       
00121       /* We waited and got no frame; sounds like digital silence or a muted digital channel */
00122       if (res == 0) {
00123          dsptime = timereqd;
00124       } else {
00125          /* Looks like we did get a frame, so let's check it out */
00126          if (!(f = ast_read(chan))) {
00127             pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
00128             break;
00129          }
00130          if (f->frametype == AST_FRAME_VOICE) {
00131             ast_dsp_func(sildet, f, &dsptime);
00132          }
00133          ast_frfree(f);
00134       }
00135 
00136       ast_verb(6, "Got %dms %s < %dms required\n", dsptime, wait_for_silence ? "silence" : "noise", timereqd);
00137 
00138       if (dsptime >= timereqd) {
00139          ast_verb(3, "Exiting with %dms %s >= %dms required\n", dsptime, wait_for_silence ? "silence" : "noise", timereqd);
00140          /* Ended happily with silence */
00141          res = 1;
00142          pbx_builtin_setvar_helper(chan, "WAITSTATUS", wait_for_silence ? "SILENCE" : "NOISE");
00143          ast_debug(1, "WAITSTATUS was set to %s\n", wait_for_silence ? "SILENCE" : "NOISE");
00144          break;
00145       }
00146 
00147       if (timeout && (difftime(time(&now), waitstart) >= timeout)) {
00148          pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
00149          ast_debug(1, "WAITSTATUS was set to TIMEOUT\n");
00150          res = 0;
00151          break;
00152       }
00153    }
00154 
00155 
00156    if (rfmt && ast_set_read_format(chan, rfmt)) {
00157       ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
00158    }
00159    ast_dsp_free(sildet);
00160    return res;
00161 }
00162 
00163 static int waitfor_exec(struct ast_channel *chan, void *data, int wait_for_silence)
00164 {
00165    int res = 1;
00166    int timereqd = 1000;
00167    int timeout = 0;
00168    int iterations = 1, i;
00169    time_t waitstart;
00170 
00171    if (chan->_state != AST_STATE_UP) {
00172       res = ast_answer(chan); /* Answer the channel */
00173    }
00174 
00175    if (!data || ( (sscanf(data, "%d,%d,%d", &timereqd, &iterations, &timeout) != 3) &&
00176       (sscanf(data, "%d,%d", &timereqd, &iterations) != 2) &&
00177       (sscanf(data, "%d", &timereqd) != 1) ) ) {
00178       ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration, no timeout\n");
00179    }
00180 
00181    ast_verb(3, "Waiting %d time(s) for %d ms silence with %d timeout\n", iterations, timereqd, timeout);
00182 
00183    time(&waitstart);
00184    res = 1;
00185    for (i=0; (i<iterations) && (res == 1); i++) {
00186       res = do_waiting(chan, timereqd, waitstart, timeout, wait_for_silence);
00187    }
00188    if (res > 0)
00189       res = 0;
00190    return res;
00191 }
00192 
00193 static int waitforsilence_exec(struct ast_channel *chan, void *data)
00194 {
00195    return waitfor_exec(chan, data, 1);
00196 }
00197 
00198 static int waitfornoise_exec(struct ast_channel *chan, void *data)
00199 {
00200    return waitfor_exec(chan, data, 0);
00201 }
00202 
00203 static int unload_module(void)
00204 {
00205    int res;
00206    res = ast_unregister_application(app_silence);
00207    res |= ast_unregister_application(app_noise);
00208 
00209    return res;
00210 }
00211 
00212 static int load_module(void)
00213 {
00214    int res;
00215 
00216    res = ast_register_application(app_silence, waitforsilence_exec, synopsis_silence, descrip_silence);
00217    res |= ast_register_application(app_noise, waitfornoise_exec, synopsis_noise, descrip_noise);
00218    return res;
00219 }
00220 
00221 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Wait For Silence");
00222 

Generated on Fri Jun 19 12:09:30 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7