Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:49 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.00 2004-01-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  *
    00029  * \ingroup applications
    00030  */
    00031
    00032 #include <stdlib.h>
    00033 #include <stdio.h>
    00034 #include <string.h>
    00035 #include <unistd.h>
    00036
    00037 #include "asterisk.h"
    00038
    00039 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211526 $")
    00040
    00041 #include "asterisk/file.h"
    00042 #include "asterisk/logger.h"
    00043 #include "asterisk/channel.h"
    00044 #include "asterisk/pbx.h"
    00045 #include "asterisk/dsp.h"
    00046 #include "asterisk/module.h"
    00047 #include "asterisk/options.h"
    00048
    00049 static char *tdesc = "Wait For Silence";
    00050 static char *app = "WaitForSilence";
    00051 static char *synopsis = "Waits for a specified amount of silence";
    00052 static char *descrip =
    00053 "  WaitForSilence(x[|y]) Wait for Silence: Waits for up to 'x' \n"
    00054 "milliseconds of silence, 'y' times or 1 if omitted\n"
    00055 "Set the channel variable WAITSTATUS with to one of these values:"
    00056 "SILENCE - if silence of x ms was detected"
    00057 "TIMEOUT - if silence of x ms was not detected."
    00058 "Examples:\n"
    00059 "  - WaitForSilence(500|2) will wait for 1/2 second of silence, twice\n"
    00060 "  - WaitForSilence(1000) will wait for 1 second of silence, once\n";
    00061
    00062 STANDARD_LOCAL_USER;
    00063
    00064 LOCAL_USER_DECL;
    00065
    00066 static int do_waiting(struct ast_channel *chan, int maxsilence) {
    00067
    00068    struct ast_frame *f;
    00069    int totalsilence = 0;
    00070    int dspsilence = 0;
    00071    int gotsilence = 0;
    00072    static int silencethreshold = 128;
    00073    int rfmt = 0;
    00074    int res = 0;
    00075    struct ast_dsp *sildet;  /* silence detector dsp */
    00076    time_t start, now;
    00077    time(&start);
    00078
    00079    rfmt = chan->readformat; /* Set to linear mode */
    00080    res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
    00081    if (res < 0) {
    00082       ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
    00083       return -1;
    00084    }
    00085
    00086    sildet = ast_dsp_new(); /* Create the silence detector */
    00087    if (!sildet) {
    00088       ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
    00089       return -1;
    00090    }
    00091    ast_dsp_set_threshold(sildet, silencethreshold);
    00092
    00093    /* Await silence... */
    00094    f = NULL;
    00095    for(;;) {
    00096       res = ast_waitfor(chan, 2000);
    00097       if (!res) {
    00098          ast_log(LOG_WARNING, "One waitfor failed, trying another\n");
    00099          /* Try one more time in case of masq */
    00100          res = ast_waitfor(chan, 2000);
    00101          if (!res) {
    00102             ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
    00103             res = -1;
    00104          }
    00105       }
    00106
    00107       if (res < 0) {
    00108          f = NULL;
    00109          break;
    00110       }
    00111       f = ast_read(chan);
    00112       if (!f)
    00113          break;
    00114       if (f->frametype == AST_FRAME_VOICE) {
    00115          dspsilence = 0;
    00116          ast_dsp_silence(sildet, f, &dspsilence);
    00117          if (dspsilence) {
    00118             totalsilence = dspsilence;
    00119             time(&start);
    00120          } else {
    00121             totalsilence = 0;
    00122          }
    00123
    00124          if (totalsilence >= maxsilence) {
    00125             if (option_verbose > 2)
    00126                ast_verbose(VERBOSE_PREFIX_3 "Exiting with %dms silence > %dms required\n", totalsilence, maxsilence);
    00127             /* Ended happily with silence */
    00128             gotsilence = 1;
    00129             pbx_builtin_setvar_helper(chan, "WAITSTATUS", "SILENCE");
    00130             ast_log(LOG_DEBUG, "WAITSTATUS was set to SILENCE\n");
    00131             ast_frfree(f);
    00132             break;
    00133          } else if ( difftime(time(&now),start) >= maxsilence/1000 ) {
    00134             pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
    00135             ast_log(LOG_DEBUG, "WAITSTATUS was set to TIMEOUT\n");
    00136             ast_frfree(f);
    00137             break;
    00138          }
    00139       }
    00140       ast_frfree(f);
    00141    }
    00142    if (rfmt && ast_set_read_format(chan, rfmt)) {
    00143       ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
    00144    }
    00145    ast_dsp_free(sildet);
    00146    return gotsilence;
    00147 }
    00148
    00149 static int waitforsilence_exec(struct ast_channel *chan, void *data)
    00150 {
    00151    int res = 1;
    00152    struct localuser *u;
    00153    int maxsilence = 1000;
    00154    int iterations = 1, i;
    00155
    00156    LOCAL_USER_ADD(u);
    00157
    00158    res = ast_answer(chan); /* Answer the channel */
    00159
    00160    if (!data || ((sscanf(data, "%30d|%30d", &maxsilence, &iterations) != 2) &&
    00161       (sscanf(data, "%30d", &maxsilence) != 1))) {
    00162       ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration\n");
    00163    }
    00164
    00165    if (option_verbose > 2)
    00166       ast_verbose(VERBOSE_PREFIX_3 "Waiting %d time(s) for %d ms silence\n", iterations, maxsilence);
    00167
    00168    res = 1;
    00169    for (i=0; (i<iterations) && (res == 1); i++) {
    00170       res = do_waiting(chan, maxsilence);
    00171    }
    00172    LOCAL_USER_REMOVE(u);
    00173    if (res > 0)
    00174       res = 0;
    00175    return res;
    00176 }
    00177
    00178 int unload_module(void)
    00179 {
    00180    int res;
    00181
    00182    res = ast_unregister_application(app);
    00183
    00184    STANDARD_HANGUP_LOCALUSERS;
    00185
    00186    return res;
    00187 }
    00188
    00189 int load_module(void)
    00190 {
    00191    return ast_register_application(app, waitforsilence_exec, synopsis, descrip);
    00192 }
    00193
    00194 char *description(void)
    00195 {
    00196    return tdesc;
    00197 }
    00198
    00199 int usecount(void)
    00200 {
    00201    int res;
    00202    STANDARD_USECOUNT(res);
    00203    return res;
    00204 }
    00205
    00206 char *key()
    00207 {
    00208    return ASTERISK_GPL_KEY;
    00209 }
    00210