Sat Feb 11 06:34:03 2012

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, const char *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_LOAD_ORDER , .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, .load_pri = AST_MODPRI_DEFAULT, }
static char * app = "BackgroundDetect"
static struct ast_module_infoast_module_info = &__mod_info


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 257 of file app_talkdetect.c.

static void __unreg_module ( void   )  [static]

Definition at line 257 of file app_talkdetect.c.

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

Definition at line 80 of file app_talkdetect.c.

References ast_channel::_state, args, ast_answer(), AST_APP_ARG, ast_canmatch_extension(), ast_channel_language(), ast_channel_name(), ast_debug, AST_DECLARE_APP_ARGS, ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), ast_format_clear(), ast_format_copy(), 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_set_read_format_by_id(), 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::caller, ast_channel::context, ast_frame_subclass::format, ast_frame::frametype, ast_format::id, ast_party_caller::id, ast_frame_subclass::integer, LOG_WARNING, ast_party_id::number, pbx_builtin_setvar_helper(), ast_channel::readformat, S_COR, ast_channel::sched, ast_party_number::str, ast_channel::stream, ast_frame::subclass, ast_channel::timingfunc, ast_dsp::totalsilence, and ast_party_number::valid.

Referenced by load_module().

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

static int load_module ( void   )  [static]

Definition at line 252 of file app_talkdetect.c.

References ast_register_application_xml, and background_detect_exec().

static int unload_module ( void   )  [static]

Definition at line 247 of file app_talkdetect.c.

References ast_unregister_application().

00248 {
00249    return ast_unregister_application(app);
00250 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 257 of file app_talkdetect.c.

char* app = "BackgroundDetect" [static]

Definition at line 78 of file app_talkdetect.c.

Definition at line 257 of file app_talkdetect.c.


Generated on Sat Feb 11 06:34:03 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6