Mon Jun 27 16:51:00 2011

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"

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 252 of file app_talkdetect.c.

static void __unreg_module ( void   )  [static]

Definition at line 252 of file app_talkdetect.c.

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

Definition at line 76 of file app_talkdetect.c.

References ast_channel::_state, args, 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::caller, ast_frame_subclass::codec, ast_channel::context, ast_frame::frametype, ast_party_caller::id, ast_frame_subclass::integer, ast_channel::language, LOG_WARNING, ast_channel::name, 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().

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

static int load_module ( void   )  [static]

Definition at line 247 of file app_talkdetect.c.

References ast_register_application_xml, and background_detect_exec().

static int unload_module ( void   )  [static]

Definition at line 242 of file app_talkdetect.c.

References ast_unregister_application().

00243 {
00244    return ast_unregister_application(app);
00245 }


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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 252 of file app_talkdetect.c.

char* app = "BackgroundDetect" [static]

Definition at line 74 of file app_talkdetect.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 252 of file app_talkdetect.c.


Generated on Mon Jun 27 16:51:00 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7