Sat Aug 6 00:39:21 2011

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: 211528 $")
00031 
00032 #include <stdlib.h>
00033 #include <stdio.h>
00034 #include <string.h>
00035 
00036 #include "asterisk/lock.h"
00037 #include "asterisk/file.h"
00038 #include "asterisk/logger.h"
00039 #include "asterisk/channel.h"
00040 #include "asterisk/pbx.h"
00041 #include "asterisk/module.h"
00042 #include "asterisk/translate.h"
00043 #include "asterisk/utils.h"
00044 #include "asterisk/dsp.h"
00045 
00046 static char *app = "BackgroundDetect";
00047 
00048 static char *synopsis = "Background a file with talk detect";
00049 
00050 static char *descrip = 
00051 "  BackgroundDetect(filename[|sil[|min|[max]]]):  Plays  back  a  given\n"
00052 "filename, waiting for interruption from a given digit (the digit must\n"
00053 "start the beginning of a valid extension, or it will be ignored).\n"
00054 "During the playback of the file, audio is monitored in the receive\n"
00055 "direction, and if a period of non-silence which is greater than 'min' ms\n"
00056 "yet less than 'max' ms is followed by silence for at least 'sil' ms then\n"
00057 "the audio playback is aborted and processing jumps to the 'talk' extension\n"
00058 "if available.  If unspecified, sil, min, and max default to 1000, 100, and\n"
00059 "infinity respectively.\n";
00060 
00061 
00062 static int background_detect_exec(struct ast_channel *chan, void *data)
00063 {
00064    int res = 0;
00065    struct ast_module_user *u;
00066    char *tmp;
00067    char *options;
00068    char *stringp;
00069    struct ast_frame *fr;
00070    int notsilent=0;
00071    struct timeval start = { 0, 0};
00072    int sil = 1000;
00073    int min = 100;
00074    int max = -1;
00075    int x;
00076    int origrformat=0;
00077    struct ast_dsp *dsp;
00078    
00079    if (ast_strlen_zero(data)) {
00080       ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n");
00081       return -1;
00082    }
00083 
00084    u = ast_module_user_add(chan);
00085 
00086    tmp = ast_strdupa(data);
00087 
00088    stringp=tmp;
00089    strsep(&stringp, "|");
00090    options = strsep(&stringp, "|");
00091    if (options) {
00092       if ((sscanf(options, "%30d", &x) == 1) && (x > 0))
00093          sil = x;
00094       options = strsep(&stringp, "|");
00095       if (options) {
00096          if ((sscanf(options, "%30d", &x) == 1) && (x > 0))
00097             min = x;
00098          options = strsep(&stringp, "|");
00099          if (options) {
00100             if ((sscanf(options, "%30d", &x) == 1) && (x > 0))
00101                max = x;
00102          }
00103       }
00104    }
00105    ast_log(LOG_DEBUG, "Preparing detect of '%s', sil=%d,min=%d,max=%d\n", 
00106                   tmp, sil, min, max);
00107    if (chan->_state != AST_STATE_UP) {
00108       /* Otherwise answer unless we're supposed to send this while on-hook */
00109       res = ast_answer(chan);
00110    }
00111    if (!res) {
00112       origrformat = chan->readformat;
00113       if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR))) 
00114          ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
00115    }
00116    if (!(dsp = ast_dsp_new())) {
00117       ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
00118       res = -1;
00119    }
00120    if (!res) {
00121       ast_stopstream(chan);
00122       res = ast_streamfile(chan, tmp, chan->language);
00123       if (!res) {
00124          while(chan->stream) {
00125             res = ast_sched_wait(chan->sched);
00126             if ((res < 0) && !chan->timingfunc) {
00127                res = 0;
00128                break;
00129             }
00130             if (res < 0)
00131                res = 1000;
00132             res = ast_waitfor(chan, res);
00133             if (res < 0) {
00134                ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name);
00135                break;
00136             } else if (res > 0) {
00137                fr = ast_read(chan);
00138                if (!fr) {
00139                   res = -1;
00140                   break;
00141                } else if (fr->frametype == AST_FRAME_DTMF) {
00142                   char t[2];
00143                   t[0] = fr->subclass;
00144                   t[1] = '\0';
00145                   if (ast_canmatch_extension(chan, chan->context, t, 1, chan->cid.cid_num)) {
00146                      /* They entered a valid  extension, or might be anyhow */
00147                      res = fr->subclass;
00148                      ast_frfree(fr);
00149                      break;
00150                   }
00151                } else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR)) {
00152                   int totalsilence;
00153                   int ms;
00154                   res = ast_dsp_silence(dsp, fr, &totalsilence);
00155                   if (res && (totalsilence > sil)) {
00156                      /* We've been quiet a little while */
00157                      if (notsilent) {
00158                         /* We had heard some talking */
00159                         ms = ast_tvdiff_ms(ast_tvnow(), start);
00160                         ms -= sil;
00161                         if (ms < 0)
00162                            ms = 0;
00163                         if ((ms > min) && ((max < 0) || (ms < max))) {
00164                            char ms_str[10];
00165                            ast_log(LOG_DEBUG, "Found qualified token of %d ms\n", ms);
00166 
00167                            /* Save detected talk time (in milliseconds) */ 
00168                            sprintf(ms_str, "%d", ms );   
00169                            pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);
00170                            
00171                            ast_goto_if_exists(chan, chan->context, "talk", 1);
00172                            res = 0;
00173                            ast_frfree(fr);
00174                            break;
00175                         } else
00176                            ast_log(LOG_DEBUG, "Found unqualified token of %d ms\n", ms);
00177                         notsilent = 0;
00178                      }
00179                   } else {
00180                      if (!notsilent) {
00181                         /* Heard some audio, mark the begining of the token */
00182                         start = ast_tvnow();
00183                         ast_log(LOG_DEBUG, "Start of voice token!\n");
00184                         notsilent = 1;
00185                      }
00186                   }
00187                   
00188                }
00189                ast_frfree(fr);
00190             }
00191             ast_sched_runq(chan->sched);
00192          }
00193          ast_stopstream(chan);
00194       } else {
00195          ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
00196          res = 0;
00197       }
00198    }
00199    if (res > -1) {
00200       if (origrformat && ast_set_read_format(chan, origrformat)) {
00201          ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n", 
00202             chan->name, ast_getformatname(origrformat));
00203       }
00204    }
00205    if (dsp)
00206       ast_dsp_free(dsp);
00207    ast_module_user_remove(u);
00208    return res;
00209 }
00210 
00211 static int unload_module(void)
00212 {
00213    int res;
00214 
00215    res = ast_unregister_application(app);
00216    
00217    ast_module_user_hangup_all();
00218 
00219    return res; 
00220 }
00221 
00222 static int load_module(void)
00223 {
00224    return ast_register_application(app, background_detect_exec, synopsis, descrip);
00225 }
00226 
00227 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Playback with Talk Detection");

Generated on Sat Aug 6 00:39:21 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7