Mon May 14 04:44:38 2007

Asterisk developer's documentation


app_talkdetect.c File Reference

Playback a file with audio detect. More...

#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/utils.h"
#include "asterisk/dsp.h"

Include dependency graph for app_talkdetect.c:

Go to the source code of this file.

Functions

 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Playback with Talk Detection")
static int background_detect_exec (struct ast_channel *chan, void *data)
static int load_module (void)
static int unload_module (void)

Variables

static char * app = "BackgroundDetect"
static char * descrip
static char * synopsis = "Background a file with talk detect"


Detailed Description

Playback a file with audio detect.

Author:
Mark Spencer <markster@digium.com>

Definition in file app_talkdetect.c.


Function Documentation

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"Playback with Talk Detection"   
)

static int background_detect_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 62 of file app_talkdetect.c.

References ast_channel::_state, ast_answer(), ast_canmatch_extension(), ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_goto_if_exists(), ast_log(), ast_module_user_add, ast_module_user_remove, ast_read(), ast_sched_runq(), ast_sched_wait(), ast_set_read_format(), AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_waitfor(), ast_frame::frametype, LOG_DEBUG, LOG_WARNING, pbx_builtin_setvar_helper(), ast_channel::readformat, strsep(), ast_frame::subclass, t, and ast_dsp::totalsilence.

Referenced by load_module().

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, "%d", &x) == 1) && (x > 0))
00093          sil = x;
00094       options = strsep(&stringp, "|");
00095       if (options) {
00096          if ((sscanf(options, "%d", &x) == 1) && (x > 0))
00097             min = x;
00098          options = strsep(&stringp, "|");
00099          if (options) {
00100             if ((sscanf(options, "%d", &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 }

static int load_module ( void   )  [static]

Definition at line 222 of file app_talkdetect.c.

References ast_register_application(), and background_detect_exec().

static int unload_module ( void   )  [static]

Definition at line 211 of file app_talkdetect.c.

References ast_module_user_hangup_all, and ast_unregister_application().

00212 {
00213    int res;
00214 
00215    res = ast_unregister_application(app);
00216    
00217    ast_module_user_hangup_all();
00218 
00219    return res; 
00220 }


Variable Documentation

char* app = "BackgroundDetect" [static]

Definition at line 46 of file app_talkdetect.c.

char* descrip [static]

Definition at line 50 of file app_talkdetect.c.

char* synopsis = "Background a file with talk detect" [static]

Definition at line 48 of file app_talkdetect.c.


Generated on Mon May 14 04:44:39 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1