Mon May 14 04:42:52 2007

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  * \ingroup applications
00033  */
00034 
00035 #include "asterisk.h"
00036 
00037 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00038 
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041 #include <string.h>
00042 #include <unistd.h>
00043 
00044 #include "asterisk/file.h"
00045 #include "asterisk/logger.h"
00046 #include "asterisk/channel.h"
00047 #include "asterisk/pbx.h"
00048 #include "asterisk/dsp.h"
00049 #include "asterisk/module.h"
00050 #include "asterisk/options.h"
00051 
00052 static char *app = "WaitForSilence";
00053 static char *synopsis = "Waits for a specified amount of silence";
00054 static char *descrip =
00055 "  WaitForSilence(silencerequired[|iterations][|timeout]) \n"
00056 "Wait for Silence: Waits for up to 'silencerequired' \n"
00057 "milliseconds of silence, 'iterations' times or once if omitted.\n"
00058 "An optional timeout specified the number of seconds to return\n"
00059 "after, even if we do not receive the specified amount of silence.\n"
00060 "Use 'timeout' with caution, as it may defeat the purpose of this\n"
00061 "application, which is to wait indefinitely until silence is detected\n"
00062 "on the line.  This is particularly useful for reverse-911-type\n"
00063 "call broadcast applications where you need to wait for an answering\n"
00064 "machine to complete its spiel before playing a message.\n"
00065 "The timeout parameter is specified only to avoid an infinite loop in\n"
00066 "cases where silence is never achieved.  Typically you will want to\n"
00067 "include two or more calls to WaitForSilence when dealing with an answering\n"
00068 "machine; first waiting for the spiel to finish, then waiting for the beep, etc.\n\n"
00069   "Examples:\n"
00070 "  - WaitForSilence(500|2) will wait for 1/2 second of silence, twice\n"
00071 "  - WaitForSilence(1000) will wait for 1 second of silence, once\n"
00072 "  - WaitForSilence(300|3|10) will wait for 300ms silence, 3 times,\n"
00073 "     and returns after 10 sec, even if silence is not detected\n\n"
00074 "Sets the channel variable WAITSTATUS with to one of these values:\n"
00075 "SILENCE - if exited with silence detected\n"
00076 "TIMEOUT - if exited without silence detected after timeout\n";
00077 
00078 static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstart, int timeout) {
00079    struct ast_frame *f;
00080    int dspsilence = 0;
00081    static int silencethreshold = 128;
00082    int rfmt = 0;
00083    int res = 0;
00084    struct ast_dsp *sildet;  /* silence detector dsp */
00085    time_t now;
00086 
00087    rfmt = chan->readformat; /* Set to linear mode */
00088    res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00089    if (res < 0) {
00090       ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n");
00091       return -1;
00092    }
00093 
00094    sildet = ast_dsp_new(); /* Create the silence detector */
00095    if (!sildet) {
00096       ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00097       return -1;
00098    }
00099    ast_dsp_set_threshold(sildet, silencethreshold);
00100 
00101    /* Await silence... */
00102    f = NULL;
00103    for(;;) {
00104       /* Start with no silence received */
00105       dspsilence = 0;
00106 
00107       res = ast_waitfor(chan, silencereqd);
00108 
00109       /* Must have gotten a hangup; let's exit */
00110       if (res <= 0) {
00111          f = NULL;
00112          break;
00113       }
00114       
00115       /* We waited and got no frame; sounds like digital silence or a muted digital channel */
00116       if (!res) {
00117          dspsilence = silencereqd;
00118       } else {
00119          /* Looks like we did get a frame, so let's check it out */
00120          f = ast_read(chan);
00121          if (!f)
00122             break;
00123          if (f && f->frametype == AST_FRAME_VOICE) {
00124             ast_dsp_silence(sildet, f, &dspsilence);
00125             ast_frfree(f);
00126          }
00127       }
00128 
00129       if (option_verbose > 6)
00130          ast_verbose(VERBOSE_PREFIX_3 "Got %dms silence< %dms required\n", dspsilence, silencereqd);
00131 
00132       if (dspsilence >= silencereqd) {
00133          if (option_verbose > 2)
00134             ast_verbose(VERBOSE_PREFIX_3 "Exiting with %dms silence >= %dms required\n", dspsilence, silencereqd);
00135          /* Ended happily with silence */
00136          res = 1;
00137          pbx_builtin_setvar_helper(chan, "WAITSTATUS", "SILENCE");
00138          ast_log(LOG_DEBUG, "WAITSTATUS was set to SILENCE\n");
00139          break;
00140       }
00141 
00142       if ( timeout && (difftime(time(&now),waitstart) >= timeout) ) {
00143          pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
00144          ast_log(LOG_DEBUG, "WAITSTATUS was set to TIMEOUT\n");
00145          res = 0;
00146          break;
00147       }
00148    }
00149 
00150 
00151    if (rfmt && ast_set_read_format(chan, rfmt)) {
00152       ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
00153    }
00154    ast_dsp_free(sildet);
00155    return res;
00156 }
00157 
00158 static int waitforsilence_exec(struct ast_channel *chan, void *data)
00159 {
00160    int res = 1;
00161    int silencereqd = 1000;
00162    int timeout = 0;
00163    int iterations = 1, i;
00164    time_t waitstart;
00165 
00166    res = ast_answer(chan); /* Answer the channel */
00167 
00168    if (!data || ( (sscanf(data, "%d|%d|%d", &silencereqd, &iterations, &timeout) != 3) &&
00169       (sscanf(data, "%d|%d", &silencereqd, &iterations) != 2) &&
00170       (sscanf(data, "%d", &silencereqd) != 1) ) ) {
00171       ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration, no timeout\n");
00172    }
00173 
00174    if (option_verbose > 2)
00175       ast_verbose(VERBOSE_PREFIX_3 "Waiting %d time(s) for %d ms silence with %d timeout\n", iterations, silencereqd, timeout);
00176 
00177    time(&waitstart);
00178    res = 1;
00179    for (i=0; (i<iterations) && (res == 1); i++) {
00180       res = do_waiting(chan, silencereqd, waitstart, timeout);
00181    }
00182    if (res > 0)
00183       res = 0;
00184    return res;
00185 }
00186 
00187 
00188 static int unload_module(void)
00189 {
00190    int res;
00191 
00192    res = ast_unregister_application(app);
00193    
00194    ast_module_user_hangup_all();
00195 
00196    return res;
00197 }
00198 
00199 static int load_module(void)
00200 {
00201    return ast_register_application(app, waitforsilence_exec, synopsis, descrip);
00202 }
00203 
00204 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Wait For Silence");
00205 

Generated on Mon May 14 04:42:52 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1