Thu Jul 9 13:40:20 2009

Asterisk developer's documentation


app_talkdetect.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  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Playback a file with audio detect
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  * 
00025  * \ingroup applications
00026  */
00027  
00028 #include "asterisk.h"
00029 
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 106140 $")
00031 
00032 #include "asterisk/lock.h"
00033 #include "asterisk/file.h"
00034 #include "asterisk/channel.h"
00035 #include "asterisk/pbx.h"
00036 #include "asterisk/module.h"
00037 #include "asterisk/translate.h"
00038 #include "asterisk/utils.h"
00039 #include "asterisk/dsp.h"
00040 #include "asterisk/app.h"
00041 
00042 static char *app = "BackgroundDetect";
00043 
00044 static char *synopsis = "Background a file with talk detect";
00045 
00046 static char *descrip = 
00047 "  BackgroundDetect(filename[,sil[,min,[max]]]):  Plays  back  a  given\n"
00048 "filename, waiting for interruption from a given digit (the digit must\n"
00049 "start the beginning of a valid extension, or it will be ignored).\n"
00050 "During the playback of the file, audio is monitored in the receive\n"
00051 "direction, and if a period of non-silence which is greater than 'min' ms\n"
00052 "yet less than 'max' ms is followed by silence for at least 'sil' ms then\n"
00053 "the audio playback is aborted and processing jumps to the 'talk' extension\n"
00054 "if available.  If unspecified, sil, min, and max default to 1000, 100, and\n"
00055 "infinity respectively.\n";
00056 
00057 
00058 static int background_detect_exec(struct ast_channel *chan, void *data)
00059 {
00060    int res = 0;
00061    char *tmp;
00062    struct ast_frame *fr;
00063    int notsilent = 0;
00064    struct timeval start = { 0, 0};
00065    int sil = 1000;
00066    int min = 100;
00067    int max = -1;
00068    int x;
00069    int origrformat=0;
00070    struct ast_dsp *dsp = NULL;
00071    AST_DECLARE_APP_ARGS(args,
00072       AST_APP_ARG(filename);
00073       AST_APP_ARG(silence);
00074       AST_APP_ARG(min);
00075       AST_APP_ARG(max);
00076    );
00077    
00078    if (ast_strlen_zero(data)) {
00079       ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n");
00080       return -1;
00081    }
00082 
00083    tmp = ast_strdupa(data);
00084    AST_STANDARD_APP_ARGS(args, tmp);
00085 
00086    if (!ast_strlen_zero(args.silence) && (sscanf(args.silence, "%d", &x) == 1) && (x > 0))
00087       sil = x;
00088    if (!ast_strlen_zero(args.min) && (sscanf(args.min, "%d", &x) == 1) && (x > 0))
00089       min = x;
00090    if (!ast_strlen_zero(args.max) && (sscanf(args.max, "%d", &x) == 1) && (x > 0))
00091       max = x;
00092 
00093    ast_debug(1, "Preparing detect of '%s', sil=%d, min=%d, max=%d\n", args.filename, sil, min, max);
00094    do {
00095       if (chan->_state != AST_STATE_UP) {
00096          if ((res = ast_answer(chan)))
00097             break;
00098       }
00099 
00100       origrformat = chan->readformat;
00101       if ((ast_set_read_format(chan, AST_FORMAT_SLINEAR))) {
00102          ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
00103          res = -1;
00104          break;
00105       }
00106 
00107       if (!(dsp = ast_dsp_new())) {
00108          ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
00109          res = -1;
00110          break;
00111       }
00112       ast_stopstream(chan);
00113       if (ast_streamfile(chan, tmp, chan->language)) {
00114          ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
00115          break;
00116       }
00117 
00118       while (chan->stream) {
00119          res = ast_sched_wait(chan->sched);
00120          if ((res < 0) && !chan->timingfunc) {
00121             res = 0;
00122             break;
00123          }
00124          if (res < 0)
00125             res = 1000;
00126          res = ast_waitfor(chan, res);
00127          if (res < 0) {
00128             ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name);
00129             break;
00130          } else if (res > 0) {
00131             fr = ast_read(chan);
00132             if (!fr) {
00133                res = -1;
00134                break;
00135             } else if (fr->frametype == AST_FRAME_DTMF) {
00136                char t[2];
00137                t[0] = fr->subclass;
00138                t[1] = '\0';
00139                if (ast_canmatch_extension(chan, chan->context, t, 1, chan->cid.cid_num)) {
00140                   /* They entered a valid  extension, or might be anyhow */
00141                   res = fr->subclass;
00142                   ast_frfree(fr);
00143                   break;
00144                }
00145             } else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR)) {
00146                int totalsilence;
00147                int ms;
00148                res = ast_dsp_silence(dsp, fr, &totalsilence);
00149                if (res && (totalsilence > sil)) {
00150                   /* We've been quiet a little while */
00151                   if (notsilent) {
00152                      /* We had heard some talking */
00153                      ms = ast_tvdiff_ms(ast_tvnow(), start);
00154                      ms -= sil;
00155                      if (ms < 0)
00156                         ms = 0;
00157                      if ((ms > min) && ((max < 0) || (ms < max))) {
00158                         char ms_str[10];
00159                         ast_debug(1, "Found qualified token of %d ms\n", ms);
00160 
00161                         /* Save detected talk time (in milliseconds) */ 
00162                         sprintf(ms_str, "%d", ms );   
00163                         pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);
00164 
00165                         ast_goto_if_exists(chan, chan->context, "talk", 1);
00166                         res = 0;
00167                         ast_frfree(fr);
00168                         break;
00169                      } else {
00170                         ast_debug(1, "Found unqualified token of %d ms\n", ms);
00171                      }
00172                      notsilent = 0;
00173                   }
00174                } else {
00175                   if (!notsilent) {
00176                      /* Heard some audio, mark the begining of the token */
00177                      start = ast_tvnow();
00178                      ast_debug(1, "Start of voice token!\n");
00179                      notsilent = 1;
00180                   }
00181                }
00182             }
00183             ast_frfree(fr);
00184          }
00185          ast_sched_runq(chan->sched);
00186       }
00187       ast_stopstream(chan);
00188    } while (0);
00189 
00190    if (res > -1) {
00191       if (origrformat && ast_set_read_format(chan, origrformat)) {
00192          ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n", 
00193             chan->name, ast_getformatname(origrformat));
00194       }
00195    }
00196    if (dsp)
00197       ast_dsp_free(dsp);
00198    return res;
00199 }
00200 
00201 static int unload_module(void)
00202 {
00203    return ast_unregister_application(app);
00204 }
00205 
00206 static int load_module(void)
00207 {
00208    return ast_register_application(app, background_detect_exec, synopsis, descrip);
00209 }
00210 
00211 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Playback with Talk Detection");

Generated on Thu Jul 9 13:40:20 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7