Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
A
asterisk
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Issue analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Voice
asterisk
Commits
e40be6c3
Commit
e40be6c3
authored
7 years ago
by
Jenkins2
Committed by
Gerrit Code Review
7 years ago
Browse files
Options
Downloads
Plain Diff
Merge "app_waitforsilence: Cleanup & don't treat missing frames as 'noise'"
parents
973885df
2b3f903e
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
apps/app_waitforsilence.c
+90
-47
90 additions, 47 deletions
apps/app_waitforsilence.c
with
90 additions
and
47 deletions
apps/app_waitforsilence.c
+
90
−
47
View file @
e40be6c3
...
...
@@ -44,6 +44,7 @@
#include
"asterisk.h"
#include
"asterisk/app.h"
#include
"asterisk/file.h"
#include
"asterisk/channel.h"
#include
"asterisk/pbx.h"
...
...
@@ -57,7 +58,9 @@
Waits for a specified amount of silence.
</synopsis>
<syntax>
<parameter name="silencerequired" required="true" />
<parameter name="silencerequired">
<para>If not specified, defaults to <literal>1000</literal> milliseconds.</para>
</parameter>
<parameter name="iterations">
<para>If not specified, defaults to <literal>1</literal>.</para>
</parameter>
...
...
@@ -101,7 +104,9 @@
Waits for a specified amount of noise.
</synopsis>
<syntax>
<parameter name="noiserequired" required="true" />
<parameter name="noiserequired">
<para>If not specified, defaults to <literal>1000</literal> milliseconds.</para>
</parameter>
<parameter name="iterations">
<para>If not specified, defaults to <literal>1</literal>.</para>
</parameter>
...
...
@@ -125,17 +130,32 @@
static
char
*
app_silence
=
"WaitForSilence"
;
static
char
*
app_noise
=
"WaitForNoise"
;
static
int
do_waiting
(
struct
ast_channel
*
chan
,
int
timereqd
,
time_t
waitstart
,
int
timeout
,
int
wait_for_silence
)
{
struct
ast_frame
*
f
=
NULL
;
int
dsptime
=
0
;
struct
wait_type
{
const
char
*
name
;
const
char
*
status
;
int
stop_on_frame_timeout
;
int
(
*
func
)(
struct
ast_dsp
*
,
struct
ast_frame
*
,
int
*
);
};
static
const
struct
wait_type
wait_for_silence
=
{
.
name
=
"silence"
,
.
status
=
"SILENCE"
,
.
stop_on_frame_timeout
=
1
,
.
func
=
ast_dsp_silence
,
};
static
const
struct
wait_type
wait_for_noise
=
{
.
name
=
"noise"
,
.
status
=
"NOISE"
,
.
stop_on_frame_timeout
=
0
,
.
func
=
ast_dsp_noise
,
};
static
int
do_waiting
(
struct
ast_channel
*
chan
,
int
timereqd
,
time_t
waitstart
,
int
timeout
,
const
struct
wait_type
*
wait_for
)
{
RAII_VAR
(
struct
ast_format
*
,
rfmt
,
NULL
,
ao2_cleanup
);
int
res
=
0
;
struct
ast_dsp
*
sildet
;
/* silence detector dsp */
time_t
now
;
/*Either silence or noise calc depending on wait_for_silence flag*/
int
(
*
ast_dsp_func
)(
struct
ast_dsp
*
,
struct
ast_frame
*
,
int
*
)
=
wait_for_silence
?
ast_dsp_silence
:
ast_dsp_noise
;
int
res
;
struct
ast_dsp
*
sildet
;
rfmt
=
ao2_bump
(
ast_channel_readformat
(
chan
));
if
((
res
=
ast_set_read_format
(
chan
,
ast_format_slin
))
<
0
)
{
...
...
@@ -145,15 +165,13 @@ static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart,
/* Create the silence detector */
if
(
!
(
sildet
=
ast_dsp_new
()))
{
ast_log
(
LOG_WARNING
,
"Unable to create silence detector
:(
\n
"
);
ast_log
(
LOG_WARNING
,
"Unable to create silence detector
\n
"
);
return
-
1
;
}
ast_dsp_set_threshold
(
sildet
,
ast_dsp_get_threshold_from_settings
(
THRESHOLD_SILENCE
));
/* Await silence... */
for
(;;)
{
/* Start with no silence received */
dsptime
=
0
;
int
dsptime
=
0
;
res
=
ast_waitfor
(
chan
,
timereqd
);
...
...
@@ -162,34 +180,36 @@ static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart,
pbx_builtin_setvar_helper
(
chan
,
"WAITSTATUS"
,
"HANGUP"
);
break
;
}
/* We waited and got no frame; sounds like digital silence or a muted digital channel */
if
(
res
==
0
)
{
dsptime
=
timereqd
;
if
(
wait_for
->
stop_on_frame_timeout
)
{
dsptime
=
timereqd
;
}
}
else
{
/* Looks like we did get a frame, so let's check it out */
if
(
!
(
f
=
ast_read
(
chan
)))
{
struct
ast_frame
*
f
=
ast_read
(
chan
);
if
(
!
f
)
{
pbx_builtin_setvar_helper
(
chan
,
"WAITSTATUS"
,
"HANGUP"
);
break
;
}
if
(
f
->
frametype
==
AST_FRAME_VOICE
)
{
ast_dsp_
func
(
sildet
,
f
,
&
dsptime
);
wait_for
->
func
(
sildet
,
f
,
&
dsptime
);
}
ast_frfree
(
f
);
}
ast_debug
(
1
,
"Got %dms %s < %dms required
\n
"
,
dsptime
,
wait_for
_silence
?
"silence"
:
"noise"
,
timereqd
);
ast_debug
(
1
,
"Got %dms
of
%s < %dms required
\n
"
,
dsptime
,
wait_for
->
name
,
timereqd
);
if
(
dsptime
>=
timereqd
)
{
ast_verb
(
3
,
"Exiting with %dms %s >= %dms required
\n
"
,
dsptime
,
wait_for_silence
?
"silence"
:
"noise"
,
timereqd
);
/* Ended happily with silence */
ast_verb
(
3
,
"Exiting with %dms of %s >= %dms required
\n
"
,
dsptime
,
wait_for
->
name
,
timereqd
);
pbx_builtin_setvar_helper
(
chan
,
"WAITSTATUS"
,
wait_for
->
status
);
ast_debug
(
1
,
"WAITSTATUS was set to %s
\n
"
,
wait_for
->
status
);
res
=
1
;
pbx_builtin_setvar_helper
(
chan
,
"WAITSTATUS"
,
wait_for_silence
?
"SILENCE"
:
"NOISE"
);
ast_debug
(
1
,
"WAITSTATUS was set to %s
\n
"
,
wait_for_silence
?
"SILENCE"
:
"NOISE"
);
break
;
}
if
(
timeout
&&
(
difftime
(
time
(
&
now
),
waitstart
)
>=
timeout
)
)
{
if
(
timeout
&&
difftime
(
time
(
NULL
),
waitstart
)
>=
timeout
)
{
pbx_builtin_setvar_helper
(
chan
,
"WAITSTATUS"
,
"TIMEOUT"
);
ast_debug
(
1
,
"WAITSTATUS was set to TIMEOUT
\n
"
);
res
=
0
;
...
...
@@ -197,61 +217,86 @@ static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart,
}
}
if
(
rfmt
&&
ast_set_read_format
(
chan
,
rfmt
))
{
ast_log
(
LOG_WARNING
,
"Unable to restore format %s to channel '%s'
\n
"
,
ast_format_get_name
(
rfmt
),
ast_channel_name
(
chan
));
}
ast_dsp_free
(
sildet
);
return
res
;
}
static
int
waitfor_exec
(
struct
ast_channel
*
chan
,
const
char
*
data
,
int
wait_for_silence
)
static
int
waitfor_exec
(
struct
ast_channel
*
chan
,
const
char
*
data
,
const
struct
wait_type
*
wait_for
)
{
int
res
=
1
;
int
timereqd
=
1000
;
int
timeout
=
0
;
int
iterations
=
1
,
i
;
time_t
waitstart
;
char
*
parse
;
struct
ast_silence_generator
*
silgen
=
NULL
;
if
(
ast_channel_state
(
chan
)
!=
AST_STATE_UP
)
{
res
=
ast_answer
(
chan
);
/* Answer the channel */
AST_DECLARE_APP_ARGS
(
args
,
AST_APP_ARG
(
timereqd
);
AST_APP_ARG
(
iterations
);
AST_APP_ARG
(
timeout
);
);
parse
=
ast_strdupa
(
data
);
AST_STANDARD_APP_ARGS
(
args
,
parse
);
if
(
!
ast_strlen_zero
(
args
.
timereqd
))
{
if
(
sscanf
(
args
.
timereqd
,
"%30d"
,
&
timereqd
)
!=
1
||
timereqd
<
0
)
{
ast_log
(
LOG_ERROR
,
"Argument '%srequired' must be an integer greater than or equal to zero.
\n
"
,
wait_for
->
name
);
return
-
1
;
}
}
if
(
!
data
||
(
(
sscanf
(
data
,
"%30d,%30d,%30d"
,
&
timereqd
,
&
iterations
,
&
timeout
)
!=
3
)
&&
(
sscanf
(
data
,
"%30d,%30d"
,
&
timereqd
,
&
iterations
)
!=
2
)
&&
(
sscanf
(
data
,
"%30d"
,
&
timereqd
)
!=
1
)
)
)
{
ast_log
(
LOG_WARNING
,
"Using default value of 1000ms, 1 iteration, no timeout
\n
"
);
if
(
!
ast_strlen_zero
(
args
.
iterations
))
{
if
(
sscanf
(
args
.
iterations
,
"%30d"
,
&
iterations
)
!=
1
||
iterations
<
1
)
{
ast_log
(
LOG_ERROR
,
"Argument 'iterations' must be an integer greater than 0.
\n
"
);
return
-
1
;
}
}
if
(
!
ast_strlen_zero
(
args
.
timeout
))
{
if
(
sscanf
(
args
.
timeout
,
"%30d"
,
&
timeout
)
!=
1
||
timeout
<
0
)
{
ast_log
(
LOG_ERROR
,
"Argument 'timeout' must be an integer greater than or equal to zero.
\n
"
);
return
-
1
;
}
}
if
(
ast_channel_state
(
chan
)
!=
AST_STATE_UP
)
{
ast_answer
(
chan
);
/* Answer the channel */
}
ast_verb
(
3
,
"Waiting %d time(s) for %d ms silence with %d timeout
\n
"
,
iterations
,
timereqd
,
timeout
);
ast_verb
(
3
,
"Waiting %d time(s) for %dms of %s with %ds timeout
\n
"
,
iterations
,
timereqd
,
wait_for
->
name
,
timeout
);
if
(
ast_opt_transmit_silence
)
{
silgen
=
ast_channel_start_silence_generator
(
chan
);
}
time
(
&
waitstart
);
res
=
1
;
for
(
i
=
0
;
(
i
<
iterations
)
&&
(
res
==
1
);
i
++
)
{
res
=
do_waiting
(
chan
,
timereqd
,
waitstart
,
timeout
,
wait_for_silence
);
for
(
i
=
0
;
i
<
iterations
&&
res
==
1
;
i
++
)
{
res
=
do_waiting
(
chan
,
timereqd
,
waitstart
,
timeout
,
wait_for
);
}
if
(
silgen
)
{
ast_channel_stop_silence_generator
(
chan
,
silgen
);
}
if
(
res
>
0
)
res
=
0
;
return
res
;
return
res
>
0
?
0
:
res
;
}
static
int
waitforsilence_exec
(
struct
ast_channel
*
chan
,
const
char
*
data
)
{
return
waitfor_exec
(
chan
,
data
,
1
);
return
waitfor_exec
(
chan
,
data
,
&
wait_for_silence
);
}
static
int
waitfornoise_exec
(
struct
ast_channel
*
chan
,
const
char
*
data
)
{
return
waitfor_exec
(
chan
,
data
,
0
);
return
waitfor_exec
(
chan
,
data
,
&
wait_for_noise
);
}
static
int
unload_module
(
void
)
...
...
@@ -272,6 +317,4 @@ static int load_module(void)
return
res
;
}
AST_MODULE_INFO_STANDARD_EXTENDED
(
ASTERISK_GPL_KEY
,
"Wait For Silence"
);
AST_MODULE_INFO_STANDARD_EXTENDED
(
ASTERISK_GPL_KEY
,
"Wait For Silence/Noise"
);
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment