Wed Oct 28 11:51:34 2009

Asterisk developer's documentation


app_talkdetect.c File Reference

Playback a file with audio detect. More...

#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/file.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 "asterisk/app.h"

Include dependency graph for app_talkdetect.c:

Go to the source code of this file.

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int background_detect_exec (struct ast_channel *chan, void *data)
static int load_module (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Playback with Talk Detection" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
static char * app = "BackgroundDetect"
static struct ast_module_infoast_module_info = &__mod_info
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

static void __reg_module ( void   )  [static]

Definition at line 233 of file app_talkdetect.c.

static void __unreg_module ( void   )  [static]

Definition at line 233 of file app_talkdetect.c.

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

Definition at line 58 of file app_talkdetect.c.

References ast_channel::_state, ast_answer(), AST_APP_ARG, ast_canmatch_extension(), ast_debug, AST_DECLARE_APP_ARGS, 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_read(), ast_sched_runq(), ast_sched_wait(), ast_set_read_format(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, ast_waitfor(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_frame::frametype, ast_channel::language, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), ast_channel::readformat, ast_channel::sched, ast_channel::stream, ast_frame::subclass, ast_channel::timingfunc, and ast_dsp::totalsilence.

Referenced by load_module().

00059 {
00060    int res = 0;
00061    char *tmp;
00062    struct ast_frame *fr;
00063    int notsilent = 0;
00064    struct timeval start = { 0, 0 };
00065    struct timeval detection_start = { 0, 0 };
00066    int sil = 1000;
00067    int min = 100;
00068    int max = -1;
00069    int analysistime = -1;
00070    int continue_analysis = 1;
00071    int x;
00072    int origrformat = 0;
00073    struct ast_dsp *dsp = NULL;
00074    AST_DECLARE_APP_ARGS(args,
00075       AST_APP_ARG(filename);
00076       AST_APP_ARG(silence);
00077       AST_APP_ARG(min);
00078       AST_APP_ARG(max);
00079       AST_APP_ARG(analysistime);
00080    );
00081    
00082    if (ast_strlen_zero(data)) {
00083       ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n");
00084       return -1;
00085    }
00086 
00087    tmp = ast_strdupa(data);
00088    AST_STANDARD_APP_ARGS(args, tmp);
00089 
00090    if (!ast_strlen_zero(args.silence) && (sscanf(args.silence, "%30d", &x) == 1) && (x > 0)) {
00091       sil = x;
00092    }
00093    if (!ast_strlen_zero(args.min) && (sscanf(args.min, "%30d", &x) == 1) && (x > 0)) {
00094       min = x;
00095    }
00096    if (!ast_strlen_zero(args.max) && (sscanf(args.max, "%30d", &x) == 1) && (x > 0)) {
00097       max = x;
00098    }
00099    if (!ast_strlen_zero(args.analysistime) && (sscanf(args.analysistime, "%30d", &x) == 1) && (x > 0)) {
00100       analysistime = x;
00101    }
00102 
00103    ast_debug(1, "Preparing detect of '%s', sil=%d, min=%d, max=%d, analysistime=%d\n", args.filename, sil, min, max, analysistime);
00104    do {
00105       if (chan->_state != AST_STATE_UP) {
00106          if ((res = ast_answer(chan))) {
00107             break;
00108          }
00109       }
00110 
00111       origrformat = chan->readformat;
00112       if ((ast_set_read_format(chan, AST_FORMAT_SLINEAR))) {
00113          ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
00114          res = -1;
00115          break;
00116       }
00117 
00118       if (!(dsp = ast_dsp_new())) {
00119          ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
00120          res = -1;
00121          break;
00122       }
00123       ast_stopstream(chan);
00124       if (ast_streamfile(chan, tmp, chan->language)) {
00125          ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
00126          break;
00127       }
00128       detection_start = ast_tvnow();
00129       while (chan->stream) {
00130          res = ast_sched_wait(chan->sched);
00131          if ((res < 0) && !chan->timingfunc) {
00132             res = 0;
00133             break;
00134          }
00135          if (res < 0) {
00136             res = 1000;
00137          }
00138          res = ast_waitfor(chan, res);
00139          if (res < 0) {
00140             ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name);
00141             break;
00142          } else if (res > 0) {
00143             fr = ast_read(chan);
00144             if (continue_analysis && analysistime >= 0) {
00145                /* If we have a limit for the time to analyze voice
00146                 * frames and the time has not expired */
00147                if (ast_tvdiff_ms(ast_tvnow(), detection_start) >= analysistime) {
00148                   continue_analysis = 0;
00149                   ast_verb(3, "BackgroundDetect: Talk analysis time complete on %s.\n", chan->name);
00150                }
00151             }
00152             
00153             if (!fr) {
00154                res = -1;
00155                break;
00156             } else if (fr->frametype == AST_FRAME_DTMF) {
00157                char t[2];
00158                t[0] = fr->subclass;
00159                t[1] = '\0';
00160                if (ast_canmatch_extension(chan, chan->context, t, 1, chan->cid.cid_num)) {
00161                   /* They entered a valid  extension, or might be anyhow */
00162                   res = fr->subclass;
00163                   ast_frfree(fr);
00164                   break;
00165                }
00166             } else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR) && continue_analysis) {
00167                int totalsilence;
00168                int ms;
00169                res = ast_dsp_silence(dsp, fr, &totalsilence);
00170                if (res && (totalsilence > sil)) {
00171                   /* We've been quiet a little while */
00172                   if (notsilent) {
00173                      /* We had heard some talking */
00174                      ms = ast_tvdiff_ms(ast_tvnow(), start);
00175                      ms -= sil;
00176                      if (ms < 0)
00177                         ms = 0;
00178                      if ((ms > min) && ((max < 0) || (ms < max))) {
00179                         char ms_str[12];
00180                         ast_debug(1, "Found qualified token of %d ms\n", ms);
00181 
00182                         /* Save detected talk time (in milliseconds) */ 
00183                         snprintf(ms_str, sizeof(ms_str), "%d", ms);  
00184                         pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);
00185 
00186                         ast_goto_if_exists(chan, chan->context, "talk", 1);
00187                         res = 0;
00188                         ast_frfree(fr);
00189                         break;
00190                      } else {
00191                         ast_debug(1, "Found unqualified token of %d ms\n", ms);
00192                      }
00193                      notsilent = 0;
00194                   }
00195                } else {
00196                   if (!notsilent) {
00197                      /* Heard some audio, mark the begining of the token */
00198                      start = ast_tvnow();
00199                      ast_debug(1, "Start of voice token!\n");
00200                      notsilent = 1;
00201                   }
00202                }
00203             }
00204             ast_frfree(fr);
00205          }
00206          ast_sched_runq(chan->sched);
00207       }
00208       ast_stopstream(chan);
00209    } while (0);
00210 
00211    if (res > -1) {
00212       if (origrformat && ast_set_read_format(chan, origrformat)) {
00213          ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n", 
00214             chan->name, ast_getformatname(origrformat));
00215       }
00216    }
00217    if (dsp) {
00218       ast_dsp_free(dsp);
00219    }
00220    return res;
00221 }

static int load_module ( void   )  [static]

Definition at line 228 of file app_talkdetect.c.

References ast_register_application, and background_detect_exec().

static int unload_module ( void   )  [static]

Definition at line 223 of file app_talkdetect.c.

References ast_unregister_application().

00224 {
00225    return ast_unregister_application(app);
00226 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Playback with Talk Detection" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 233 of file app_talkdetect.c.

char* app = "BackgroundDetect" [static]

Definition at line 42 of file app_talkdetect.c.

Definition at line 233 of file app_talkdetect.c.

char* descrip [static]

Definition at line 46 of file app_talkdetect.c.

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

Definition at line 44 of file app_talkdetect.c.


Generated on Wed Oct 28 11:51:35 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6