00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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: 29555 $")
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;
00076 time_t start, now;
00077 time(&start);
00078
00079 rfmt = chan->readformat;
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();
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
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
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
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);
00159
00160 if (!data || ((sscanf(data, "%d|%d", &maxsilence, &iterations) != 2) &&
00161 (sscanf(data, "%d", &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