#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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
| static char * | app = "BackgroundDetect" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
Definition in file app_talkdetect.c.
| 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().
00253 { 00254 return ast_register_application_xml(app, background_detect_exec); 00255 }
| 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 }
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.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 257 of file app_talkdetect.c.
1.5.6