diff --git a/apps/Makefile b/apps/Makefile index 449379beeef86fa7c97e8db0b90eb6e6847a730c..a50ac8091d6410898c0e9535d722742d2116ba17 100755 --- a/apps/Makefile +++ b/apps/Makefile @@ -30,7 +30,7 @@ APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\ app_groupcount.so app_txtcidname.so app_controlplayback.so \ app_talkdetect.so app_alarmreceiver.so app_userevent.so app_verbose.so \ app_test.so app_forkcdr.so app_math.so app_realtime.so \ - app_dumpchan.so + app_dumpchan.so app_waitforsilence.so ifneq (${OSARCH},Darwin) APPS+=app_intercom.so diff --git a/apps/app_waitforsilence.c b/apps/app_waitforsilence.c new file mode 100755 index 0000000000000000000000000000000000000000..b29286a36d8b6b36b3f923c4257e4f3f16e673f5 --- /dev/null +++ b/apps/app_waitforsilence.c @@ -0,0 +1,168 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Copyright (C) 1999-2004, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * Wait for Silence + * - Waits for up to 'x' milliseconds of silence, 'y' times + * - WaitForSilence(500,2) will wait for 1/2 second of silence, twice + * - WaitForSilence(1000,1) will wait for 1 second of silence, once + * + * WaitForSilence Application by David C. Troy <dave@popvox.com> + * Version 1.00 2004-01-29 + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + +#include <asterisk/file.h> +#include <asterisk/logger.h> +#include <asterisk/channel.h> +#include <asterisk/pbx.h> +#include <asterisk/dsp.h> +#include <asterisk/module.h> +#include <asterisk/options.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> + +static char *tdesc = "Wait For Silence"; +static char *app = "WaitForSilence"; +static char *synopsis = "Waits for a specified amount of silence"; +static char *descrip = +" WaitForSilence(x[|y]) Wait for Silence: Waits for up to 'x' \n" +"milliseconds of silence, 'y' times or 1 if omitted\n" +"Examples:\n" +" - WaitForSilence(500,2) will wait for 1/2 second of silence, twice\n" +" - WaitForSilence(1000) will wait for 1 second of silence, once\n"; + +STANDARD_LOCAL_USER; + +LOCAL_USER_DECL; + +static int do_waiting(struct ast_channel *chan, int duration) { + + struct ast_frame *f; + int totalsilence = 0; + int dspsilence = 0; + int gotsilence = 0; + static int silencethreshold = 64; + int rfmt = 0; + int res = 0; + struct ast_dsp *sildet; /* silence detector dsp */ + + rfmt = chan->readformat; /* Set to linear mode */ + res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); + if (res < 0) { + ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); + return -1; + } + + sildet = ast_dsp_new(); /* Create the silence detector */ + if (!sildet) { + ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); + return -1; + } + ast_dsp_set_threshold(sildet, silencethreshold); + + /* Await silence... */ + f = NULL; + for(;;) { + res = ast_waitfor(chan, 2000); + if (!res) { + ast_log(LOG_WARNING, "One waitfor failed, trying another\n"); + /* Try one more time in case of masq */ + res = ast_waitfor(chan, 2000); + if (!res) { + ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name); + res = -1; + } + } + + if (res < 0) { + f = NULL; + break; + } + f = ast_read(chan); + if (!f) + break; + if (f->frametype == AST_FRAME_VOICE) { + dspsilence = 0; + ast_dsp_silence(sildet, f, &dspsilence); + if (dspsilence) + totalsilence = dspsilence; + else + totalsilence = 0; + /* ast_verbose(VERBOSE_PREFIX_3 "dspsilence: %d, totalsilence: %d\n", dspsilence, totalsilence); */ + + if (totalsilence >= duration) { + ast_verbose(VERBOSE_PREFIX_3 "exiting with %d silence > %d required\n", totalsilence, duration); + /* Ended happily with silence */ + ast_frfree(f); + gotsilence = 1; + break; + } + } + ast_frfree(f); + } + ast_dsp_free(sildet); + return gotsilence; +} + +static int waitforsilence_exec(struct ast_channel *chan, void *data) +{ + int res=1; + struct localuser *u; + int duration = 1000; + int iterations = 1, i; + + res = ast_answer(chan); /* Answer the channel */ + + if (!data || ((sscanf(data, "%d|%d", &duration, &iterations) != 2) && + (sscanf(data, "%d", &duration != 1)))) { + ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration\n"); + } + + ast_verbose(VERBOSE_PREFIX_3 "Waiting %d time(s) for %d ms silence\n", iterations, duration); + LOCAL_USER_ADD(u); + res = 1; + for ( i=0; (i<iterations) && (res == 1); i++) { + res = do_waiting(chan, duration); + } + LOCAL_USER_REMOVE(u); + if (res > 0) + res = 0; + return res; +} + +int unload_module(void) +{ + STANDARD_HANGUP_LOCALUSERS; + return ast_unregister_application(app); +} + +int load_module(void) +{ + return ast_register_application(app, waitforsilence_exec, synopsis, descrip); +} + +char *description(void) +{ + return tdesc; +} + +int usecount(void) +{ + int res; + STANDARD_USECOUNT(res); + return res; +} + +char *key() +{ + return ASTERISK_GPL_KEY; +} +