diff --git a/apps/app_amd.c b/apps/app_amd.c index 850fda37ce39e88cad2647de477e9765478232db..f44c1af205745d44ffdb833eb416683e99900d50 100644 --- a/apps/app_amd.c +++ b/apps/app_amd.c @@ -91,7 +91,7 @@ static int dfltSilenceThreshold = 256; static void isAnsweringMachine(struct ast_channel *chan, void *data) { - int res = 0; + int res = 0, ret = 0; struct ast_frame *f = NULL; @@ -136,8 +136,8 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data) AST_APP_ARG(argMaximumNumberOfWords); AST_APP_ARG(argSilenceThreshold); ); - - ast_verbose(VERBOSE_PREFIX_3 "AMD: %s %s %s (Fmt: %d)\n", chan->name ,chan->cid.cid_ani, chan->cid.cid_rdnis, chan->readformat); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: %s %s %s (Fmt: %d)\n", chan->name ,chan->cid.cid_ani, chan->cid.cid_rdnis, chan->readformat); /* Lets parse the arguments. */ if (ast_strlen_zero(data)) { @@ -180,8 +180,9 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data) } /* Now we're ready to roll! */ - - ast_verbose(VERBOSE_PREFIX_3 "AMD: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] " + + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] " "totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] \n", initialSilence, greeting, afterGreetingSilence, totalAnalysisTime, minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold ); @@ -204,42 +205,56 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data) } ast_dsp_set_threshold(silenceDetector, silenceThreshold ); - while (ast_waitfor(chan, -1) > -1) + while ((ret = ast_waitfor(chan, totalAnalysisTime))) { - f = ast_read(chan); - if (!f ) { + if (ret < 0) { /* No Frame: Called Party Must Have Dropped */ - ast_verbose(VERBOSE_PREFIX_3 "AMD: HANGUP\n"); - ast_log(LOG_DEBUG, "Got hangup\n"); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: HANGUP\n"); + if (option_debug) + ast_log(LOG_DEBUG, "Got hangup\n"); strcpy(amdStatus , "HANGUP" ); strcpy(amdCause , "" ); break; } - framelength = (ast_codec_get_samples(f) / 8); - iTotalTime += framelength; - if (iTotalTime >= totalAnalysisTime ) { - ast_verbose(VERBOSE_PREFIX_3 "AMD: Channel [%s]. Too long...\n", chan->name ); - ast_frfree(f); - strcpy(amdStatus , "NOTSURE" ); - sprintf(amdCause , "TOOLONG-%d", iTotalTime ); + f = ast_read(chan); + if (!f ) { + /* No Frame: Called Party Must Have Dropped */ + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: HANGUP\n"); + if (option_debug) + ast_log(LOG_DEBUG, "Got hangup\n"); + strcpy(amdStatus , "HANGUP" ); + strcpy(amdCause , "" ); break; } if (f->frametype == AST_FRAME_VOICE ) { + framelength = (ast_codec_get_samples(f) / DEFAULT_SAMPLES_PER_MS); + iTotalTime += framelength; + if (iTotalTime >= totalAnalysisTime ) { + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: Channel [%s]. Too long...\n", chan->name ); + ast_frfree(f); + strcpy(amdStatus , "NOTSURE" ); + sprintf(amdCause , "TOOLONG-%d", iTotalTime ); + break; + } dspsilence = 0; ast_dsp_silence(silenceDetector, f, &dspsilence); if (dspsilence ) { silenceDuration = dspsilence; - /* ast_verbose(VERBOSE_PREFIX_3 "AMD: %d SILENCE: silenceDuration:%d afterGreetingSilence:%d inGreeting:%d\n", currentState, silenceDuration, afterGreetingSilence, inGreeting ); */ if (silenceDuration >= betweenWordsSilence ) { if (currentState != STATE_IN_SILENCE ) { previousState = currentState; - ast_verbose(VERBOSE_PREFIX_3 "AMD: Changed state to STATE_IN_SILENCE\n"); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: Changed state to STATE_IN_SILENCE\n"); } currentState = STATE_IN_SILENCE; consecutiveVoiceDuration = 0; } if (inInitialSilence == 1 && silenceDuration >= initialSilence ) { - ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: silenceDuration:%d initialSilence:%d\n", + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: silenceDuration:%d initialSilence:%d\n", silenceDuration, initialSilence ); ast_frfree(f); strcpy(amdStatus , "MACHINE" ); @@ -248,7 +263,8 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data) } if (silenceDuration >= afterGreetingSilence && inGreeting == 1 ) { - ast_verbose(VERBOSE_PREFIX_3 "AMD: HUMAN: silenceDuration:%d afterGreetingSilence:%d\n", + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: HUMAN: silenceDuration:%d afterGreetingSilence:%d\n", silenceDuration, afterGreetingSilence ); ast_frfree(f); strcpy(amdStatus , "HUMAN" ); @@ -258,21 +274,22 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data) } else { consecutiveVoiceDuration += framelength; voiceDuration += framelength; - /* ast_verbose(VERBOSE_PREFIX_3 "AMD: %d VOICE: ConsecutiveVoice:%d voiceDuration:%d inGreeting:%d\n", currentState, consecutiveVoiceDuration, voiceDuration, inGreeting ); */ /* If I have enough consecutive voice to say that I am in a Word, I can only increment the number of words if my previous state was Silence, which means that I moved into a word. */ if (consecutiveVoiceDuration >= minimumWordLength ) { if (currentState == STATE_IN_SILENCE ) { iWordsCount++; - ast_verbose(VERBOSE_PREFIX_3 "AMD: Word detected. iWordsCount:%d\n", iWordsCount ); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: Word detected. iWordsCount:%d\n", iWordsCount ); previousState = currentState; currentState = STATE_IN_WORD; } } if (iWordsCount >= maximumNumberOfWords ) { - ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: iWordsCount:%d\n", iWordsCount ); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: iWordsCount:%d\n", iWordsCount ); ast_frfree(f); strcpy(amdStatus , "MACHINE" ); sprintf(amdCause , "MAXWORDS-%d-%d", iWordsCount, maximumNumberOfWords ); @@ -280,9 +297,9 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data) } if (inGreeting == 1 && voiceDuration >= greeting ) { - ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: voiceDuration:%d greeting:%d\n", - voiceDuration, greeting ); - ast_frfree(f); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: voiceDuration:%d greeting:%d\n", voiceDuration, greeting); + ast_frfree(f); strcpy(amdStatus , "MACHINE" ); sprintf(amdCause , "LONGGREETING-%d-%d", voiceDuration, greeting ); break; @@ -296,12 +313,19 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data) } ast_frfree(f); } + if (!ret) { + /* It took too long to get a frame back. Giving up. */ + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: Channel [%s]. Too long...\n", chan->name ); + strcpy(amdStatus , "NOTSURE" ); + sprintf(amdCause , "TOOLONG-%d", iTotalTime ); + } pbx_builtin_setvar_helper(chan , "AMDSTATUS" , amdStatus ); pbx_builtin_setvar_helper(chan , "AMDCAUSE" , amdCause ); /* If We Started With A Valid Read Format, Return To It... */ - if (readFormat) { + if (readFormat && chan->_state == AST_STATE_UP) { res = ast_set_read_format(chan, readFormat ); if (res) ast_log(LOG_WARNING, "AMD: Unable to restore read format on '%s'\n", chan->name); @@ -371,7 +395,8 @@ static void load_config(void) } ast_config_destroy(cfg); - ast_verbose(VERBOSE_PREFIX_3 "AMD defaults: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] " + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD defaults: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] " "totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] \n", dfltInitialSilence, dfltGreeting, dfltAfterGreetingSilence, dfltTotalAnalysisTime, dfltMinimumWordLength, dfltBetweenWordsSilence, dfltMaximumNumberOfWords, dfltSilenceThreshold );