Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:16 2009

## Asterisk developer's documentation

# app_talkdetect.c File Reference

Playback a file with audio detect. More...

`#include <stdlib.h>`
`#include <stdio.h>`
`#include <string.h>`
`#include "asterisk.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

static int | background_detect_exec (struct ast_channel *chan, void *data)
char * | description (void)
| Provides a description of the module.
char * | key ()
| Returns the ASTERISK_GPL_KEY.
int | load_module (void)
| Initialize the module.
int | unload_module (void)
| Cleanup all module structures, sockets, etc.
int | usecount (void)
| Provides a usecount.

## Variables

static char * | app = "BackgroundDetect"
static char * | descrip
| LOCAL_USER_DECL
| STANDARD_LOCAL_USER
static char * | synopsis = "Background a file with talk detect"
static char * | tdesc = "Playback with Talk Detection"

## Detailed Description

Playback a file with audio detect.

Definition in file app_talkdetect.c.

## Function Documentation

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

Definition at line 65 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_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_channel::cid, ast_callerid::cid_num, ast_channel::context, dsp, ast_frame::frametype, ast_channel::language, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), ast_channel::readformat, ast_channel::sched, ast_channel::stream, strsep(), ast_frame::subclass, t, ast_channel::timingfunc, and ast_dsp::totalsilence.

Referenced by load_module().

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

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 235 of file app_talkdetect.c.

    00236 {
    00237    return tdesc;
    00238 }

char* key | ( | void |  | ) |

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

     char *key(void) {
             return ASTERISK_GPL_KEY;
     }

Returns:
  ASTERISK_GPL_KEY

Definition at line 247 of file app_talkdetect.c.

References ASTERISK_GPL_KEY.

    00248 {
    00249    return ASTERISK_GPL_KEY;
    00250 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
  int Always 0.

TE STUFF END

Definition at line 230 of file app_talkdetect.c.

References ast_register_application(), and background_detect_exec().

    00231 {
    00232    return ast_register_application(app, background_detect_exec, synopsis, descrip);
    00233 }

int unload_module | ( | void |  | ) |

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
  Zero on success, or non-zero on error.

Definition at line 219 of file app_talkdetect.c.

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

    00220 {
    00221    int res;
    00222
    00223    res = ast_unregister_application(app);
    00224
    00225    STANDARD_HANGUP_LOCALUSERS;
    00226
    00227    return res;
    00228 }

int usecount | ( | void |  | ) |

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
  The module's usecount.

Definition at line 240 of file app_talkdetect.c.

References STANDARD_USECOUNT.

    00241 {
    00242    int res;
    00243    STANDARD_USECOUNT(res);
    00244    return res;
    00245 }

## 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.

LOCAL_USER_DECL

Definition at line 63 of file app_talkdetect.c.

STANDARD_LOCAL_USER

Definition at line 61 of file app_talkdetect.c.

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

Definition at line 48 of file app_talkdetect.c.

char* tdesc = "Playback with Talk Detection"`[static]`

Definition at line 44 of file app_talkdetect.c.