92
92
<para>Is the maximum duration of a word to accept.</para>
93
93
<para>If exceeded, then the result is detection as a MACHINE</para>
94
94
</parameter>
95
+ <parameter name="audioFile" required="false">
96
+ <para>Is an audio file to play to the caller while AMD is in progress.</para>
97
+ <para>By default, no audio file is played.</para>
98
+ <para>If an audio file is configured in amd.conf, then that file will be used
99
+ if one is not specified here. That file may be overridden by this argument.</para>
100
+ </parameter>
95
101
</syntax>
96
102
<description>
97
103
<para>This application attempts to detect answering machines at the beginning
@@ -155,6 +161,9 @@ static int dfltBetweenWordsSilence = 50;
155
161
static int dfltMaximumNumberOfWords = 2 ;
156
162
static int dfltSilenceThreshold = 256 ;
157
163
static int dfltMaximumWordLength = 5000 ; /* Setting this to a large default so it is not used unless specify it in the configs or command line */
164
+ static char * dfltAudioFile = NULL ;
165
+
166
+ static ast_mutex_t config_lock ;
158
167
159
168
/* Set to the lowest ms value provided in amd.conf or application parameters */
160
169
static int dfltMaxWaitTimeForFrame = 50 ;
@@ -179,7 +188,7 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
179
188
char amdCause [256 ] = "" , amdStatus [256 ] = "" ;
180
189
char * parse = ast_strdupa (data );
181
190
182
- /* Lets set the initial values of the variables that will control the algorithm.
191
+ /* Let's set the initial values of the variables that will control the algorithm.
183
192
The initial values are the default ones. If they are passed as arguments
184
193
when invoking the application, then the default values will be overwritten
185
194
by the ones passed as parameters. */
@@ -193,6 +202,7 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
193
202
int silenceThreshold = dfltSilenceThreshold ;
194
203
int maximumWordLength = dfltMaximumWordLength ;
195
204
int maxWaitTimeForFrame = dfltMaxWaitTimeForFrame ;
205
+ const char * audioFile = NULL ;
196
206
197
207
AST_DECLARE_APP_ARGS (args ,
198
208
AST_APP_ARG (argInitialSilence );
@@ -204,8 +214,15 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
204
214
AST_APP_ARG (argMaximumNumberOfWords );
205
215
AST_APP_ARG (argSilenceThreshold );
206
216
AST_APP_ARG (argMaximumWordLength );
217
+ AST_APP_ARG (audioFile );
207
218
);
208
219
220
+ ast_mutex_lock (& config_lock );
221
+ if (!ast_strlen_zero (dfltAudioFile )) {
222
+ audioFile = ast_strdupa (dfltAudioFile );
223
+ }
224
+ ast_mutex_unlock (& config_lock );
225
+
209
226
ast_verb (3 , "AMD: %s %s %s (Fmt: %s)\n" , ast_channel_name (chan ),
210
227
S_COR (ast_channel_caller (chan )-> ani .number .valid , ast_channel_caller (chan )-> ani .number .str , "(N/A)" ),
211
228
S_COR (ast_channel_redirecting (chan )-> from .number .valid , ast_channel_redirecting (chan )-> from .number .str , "(N/A)" ),
@@ -233,6 +250,9 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
233
250
silenceThreshold = atoi (args .argSilenceThreshold );
234
251
if (!ast_strlen_zero (args .argMaximumWordLength ))
235
252
maximumWordLength = atoi (args .argMaximumWordLength );
253
+ if (!ast_strlen_zero (args .audioFile )) {
254
+ audioFile = args .audioFile ;
255
+ }
236
256
} else {
237
257
ast_debug (1 , "AMD using the default parameters.\n" );
238
258
}
@@ -280,6 +300,11 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
280
300
/* Set our start time so we can tie the loop to real world time and not RTP updates */
281
301
amd_tvstart = ast_tvnow ();
282
302
303
+ /* Optional audio file to play to caller while AMD is doing its thing. */
304
+ if (!ast_strlen_zero (audioFile )) {
305
+ ast_streamfile (chan , audioFile , ast_channel_language (chan ));
306
+ }
307
+
283
308
/* Now we go into a loop waiting for frames from the channel */
284
309
while ((res = ast_waitfor (chan , 2 * maxWaitTimeForFrame )) > -1 ) {
285
310
int ms = 0 ;
@@ -462,10 +487,14 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
462
487
/* Free the DSP used to detect silence */
463
488
ast_dsp_free (silenceDetector );
464
489
490
+ /* If we were playing something to pass the time, stop it now. */
491
+ if (!ast_strlen_zero (audioFile )) {
492
+ ast_stopstream (chan );
493
+ }
494
+
465
495
return ;
466
496
}
467
497
468
-
469
498
static int amd_exec (struct ast_channel * chan , const char * data )
470
499
{
471
500
isAnsweringMachine (chan , data );
@@ -516,7 +545,16 @@ static int load_config(int reload)
516
545
dfltMaximumNumberOfWords = atoi (var -> value );
517
546
} else if (!strcasecmp (var -> name , "maximum_word_length" )) {
518
547
dfltMaximumWordLength = atoi (var -> value );
519
-
548
+ } else if (!strcasecmp (var -> name , "playback_file" )) {
549
+ ast_mutex_lock (& config_lock );
550
+ if (dfltAudioFile ) {
551
+ ast_free (dfltAudioFile );
552
+ dfltAudioFile = NULL ;
553
+ }
554
+ if (!ast_strlen_zero (var -> value )) {
555
+ dfltAudioFile = ast_strdup (var -> value );
556
+ }
557
+ ast_mutex_unlock (& config_lock );
520
558
} else {
521
559
ast_log (LOG_WARNING , "%s: Cat:%s. Unknown keyword %s at line %d of amd.conf\n" ,
522
560
app , cat , var -> name , var -> lineno );
@@ -539,6 +577,12 @@ static int load_config(int reload)
539
577
540
578
static int unload_module (void )
541
579
{
580
+ ast_mutex_lock (& config_lock );
581
+ if (dfltAudioFile ) {
582
+ ast_free (dfltAudioFile );
583
+ }
584
+ ast_mutex_unlock (& config_lock );
585
+ ast_mutex_destroy (& config_lock );
542
586
return ast_unregister_application (app );
543
587
}
544
588
@@ -554,6 +598,7 @@ static int unload_module(void)
554
598
*/
555
599
static int load_module (void )
556
600
{
601
+ ast_mutex_init (& config_lock );
557
602
if (load_config (0 ) || ast_register_application_xml (app , amd_exec )) {
558
603
return AST_MODULE_LOAD_DECLINE ;
559
604
}
0 commit comments