Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
Data Structures | Macros | Functions | Variables
func_talkdetect.c File Reference

Function that raises events when talking is detected on a channel. More...

#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/audiohook.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
Include dependency graph for func_talkdetect.c:

Go to the source code of this file.

Data Structures

struct  talk_detect_params
 Private data structure used with the function's datastore. More...
 

Macros

#define DEFAULT_SILENCE_THRESHOLD   2500
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void datastore_destroy_cb (void *data)
 
static int load_module (void)
 
static int remove_talk_detect (struct ast_channel *chan)
 
static int set_talk_detect (struct ast_channel *chan, int dsp_silence_threshold, int dsp_talking_threshold)
 
static int talk_detect_audiohook_cb (struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
 
static int talk_detect_fn_write (struct ast_channel *chan, const char *function, char *data, const char *value)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Talk detection dialplan function" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const struct ast_datastore_info talk_detect_datastore
 The channel datastore the function uses to store state.
 
static struct ast_custom_function talk_detect_function
 Definition of the TALK_DETECT function.
 

Detailed Description

Function that raises events when talking is detected on a channel.

Author
Matt Jordan mjord.nosp@m.an@d.nosp@m.igium.nosp@m..com

Definition in file func_talkdetect.c.

Macro Definition Documentation

◆ DEFAULT_SILENCE_THRESHOLD

#define DEFAULT_SILENCE_THRESHOLD   2500

Definition at line 136 of file func_talkdetect.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 424 of file func_talkdetect.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 424 of file func_talkdetect.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 424 of file func_talkdetect.c.

◆ datastore_destroy_cb()

static void datastore_destroy_cb ( void *  data)
static

Definition at line 155 of file func_talkdetect.c.

155 {
156 struct talk_detect_params *td_params = data;
157
158 ast_audiohook_destroy(&td_params->audiohook);
159
160 if (td_params->dsp) {
161 ast_dsp_free(td_params->dsp);
162 }
163 ast_free(data);
164}
#define ast_free(a)
Definition astmm.h:180
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
Definition audiohook.c:124
void ast_dsp_free(struct ast_dsp *dsp)
Definition dsp.c:1787
Private data structure used with the function's datastore.
struct ast_audiohook audiohook
struct ast_dsp * dsp

References ast_audiohook_destroy(), ast_dsp_free(), ast_free, talk_detect_params::audiohook, and talk_detect_params::dsp.

◆ load_module()

static int load_module ( void  )
static

Definition at line 415 of file func_talkdetect.c.

416{
417 int res = 0;
418
420
422}
static struct ast_custom_function talk_detect_function
Definition of the TALK_DETECT function.
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
#define ast_custom_function_register(acf)
Register a custom function.
Definition pbx.h:1562

References ast_custom_function_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, and talk_detect_function.

◆ remove_talk_detect()

static int remove_talk_detect ( struct ast_channel chan)
static

Definition at line 250 of file func_talkdetect.c.

251{
252 struct ast_datastore *datastore = NULL;
253 struct talk_detect_params *td_params;
254 SCOPED_CHANNELLOCK(chan_lock, chan);
255
257 if (!datastore) {
258 ast_log(AST_LOG_WARNING, "Cannot remove TALK_DETECT from %s: TALK_DETECT not currently enabled\n",
259 ast_channel_name(chan));
260 return -1;
261 }
262 td_params = datastore->data;
263
264 if (ast_audiohook_remove(chan, &td_params->audiohook)) {
265 ast_log(AST_LOG_WARNING, "Failed to remove TALK_DETECT audiohook from channel %s\n",
266 ast_channel_name(chan));
267 return -1;
268 }
269
270 if (ast_channel_datastore_remove(chan, datastore)) {
271 ast_log(AST_LOG_WARNING, "Failed to remove TALK_DETECT datastore from channel %s\n",
272 ast_channel_name(chan));
273 return -1;
274 }
275 ast_datastore_free(datastore);
276
277 return 0;
278}
#define ast_log
Definition astobj2.c:42
int ast_audiohook_remove(struct ast_channel *chan, struct ast_audiohook *audiohook)
Remove an audiohook from a specified channel.
Definition audiohook.c:758
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition channel.c:2384
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition channel.c:2389
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition datastore.c:68
static const struct ast_datastore_info talk_detect_datastore
The channel datastore the function uses to store state.
#define AST_LOG_WARNING
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition lock.h:626
#define NULL
Definition resample.c:96
Structure for a data store object.
Definition datastore.h:64
void * data
Definition datastore.h:66

References ast_audiohook_remove(), ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_name(), ast_datastore_free(), ast_log, AST_LOG_WARNING, talk_detect_params::audiohook, ast_datastore::data, NULL, SCOPED_CHANNELLOCK, and talk_detect_datastore.

Referenced by talk_detect_fn_write().

◆ set_talk_detect()

static int set_talk_detect ( struct ast_channel chan,
int  dsp_silence_threshold,
int  dsp_talking_threshold 
)
static

Definition at line 281 of file func_talkdetect.c.

282{
283 struct ast_datastore *datastore = NULL;
284 struct talk_detect_params *td_params;
285 SCOPED_CHANNELLOCK(chan_lock, chan);
286
288 if (!datastore) {
290 if (!datastore) {
291 return -1;
292 }
293
294 td_params = ast_calloc(1, sizeof(*td_params));
295 if (!td_params) {
296 ast_datastore_free(datastore);
297 return -1;
298 }
299
300 ast_audiohook_init(&td_params->audiohook,
302 "TALK_DETECT",
306
308 if (!td_params->dsp) {
309 ast_datastore_free(datastore);
310 ast_free(td_params);
311 return -1;
312 }
313 datastore->data = td_params;
314
315 ast_channel_datastore_add(chan, datastore);
316 ast_audiohook_attach(chan, &td_params->audiohook);
317 } else {
318 /* Talk detection already enabled; update existing settings */
319 td_params = datastore->data;
320 }
321
324
325 ast_dsp_set_threshold(td_params->dsp, td_params->dsp_talking_threshold);
326
327 return 0;
328}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
@ AST_AUDIOHOOK_MANIPULATE_ALL_RATES
Definition audiohook.h:75
int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source, enum ast_audiohook_init_flags flags)
Initialize an audiohook structure.
Definition audiohook.c:100
@ AST_AUDIOHOOK_TRIGGER_READ
Definition audiohook.h:56
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition audiohook.c:521
@ AST_AUDIOHOOK_TYPE_MANIPULATE
Definition audiohook.h:38
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition channel.c:2375
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
#define ast_datastore_alloc(info, uid)
Definition datastore.h:85
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set the minimum average magnitude threshold to determine talking by the DSP.
Definition dsp.c:1792
struct ast_dsp * ast_dsp_new_with_rate(unsigned int sample_rate)
Allocates a new dsp with a specific internal sample rate used during processing.
Definition dsp.c:1767
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition format.c:379
static int talk_detect_audiohook_cb(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
ast_audiohook_manipulate_callback manipulate_callback
Definition audiohook.h:118
#define ast_set_flag(p, flag)
Definition utils.h:71

References ast_audiohook_attach(), ast_audiohook_init(), AST_AUDIOHOOK_MANIPULATE_ALL_RATES, AST_AUDIOHOOK_TRIGGER_READ, AST_AUDIOHOOK_TYPE_MANIPULATE, ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_rawreadformat(), ast_datastore_alloc, ast_datastore_free(), ast_dsp_new_with_rate(), ast_dsp_set_threshold(), ast_format_get_sample_rate(), ast_free, ast_set_flag, talk_detect_params::audiohook, ast_datastore::data, talk_detect_params::dsp, talk_detect_params::dsp_silence_threshold, talk_detect_params::dsp_talking_threshold, ast_audiohook::manipulate_callback, NULL, SCOPED_CHANNELLOCK, talk_detect_audiohook_cb(), and talk_detect_datastore.

Referenced by talk_detect_fn_write().

◆ talk_detect_audiohook_cb()

static int talk_detect_audiohook_cb ( struct ast_audiohook audiohook,
struct ast_channel chan,
struct ast_frame frame,
enum ast_audiohook_direction  direction 
)
static

Definition at line 180 of file func_talkdetect.c.

181{
182 int total_silence;
183 int is_talking;
184 int update_talking = 0;
185 struct ast_datastore *datastore;
186 struct talk_detect_params *td_params;
187 struct stasis_message *message;
188
189 if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
190 return 1;
191 }
192
194 return 1;
195 }
196
197 if (frame->frametype != AST_FRAME_VOICE) {
198 return 1;
199 }
200
201 if (!(datastore = ast_channel_datastore_find(chan, &talk_detect_datastore, NULL))) {
202 return 1;
203 }
204 td_params = datastore->data;
205
206 is_talking = !ast_dsp_silence(td_params->dsp, frame, &total_silence);
207 if (is_talking) {
208 if (!td_params->talking) {
209 update_talking = 1;
210 td_params->talking_start = ast_tvnow();
211 }
212 td_params->talking = 1;
213 } else if (total_silence >= td_params->dsp_silence_threshold) {
214 if (td_params->talking) {
215 update_talking = 1;
216 }
217 td_params->talking = 0;
218 }
219
220 if (update_talking) {
221 struct ast_json *blob = NULL;
222
223 if (!td_params->talking) {
224 int64_t diff_ms = ast_tvdiff_ms(ast_tvnow(), td_params->talking_start);
225 diff_ms -= td_params->dsp_silence_threshold;
226
227 blob = ast_json_pack("{s: I}", "duration", (ast_json_int_t)diff_ms);
228 if (!blob) {
229 return 1;
230 }
231 }
232
233 ast_verb(4, "%s is now %s\n", ast_channel_name(chan),
234 td_params->talking ? "talking" : "silent");
237 blob);
238 if (message) {
240 ao2_ref(message, -1);
241 }
242
243 ast_json_unref(blob);
244 }
245
246 return 1;
247}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
@ AST_AUDIOHOOK_DIRECTION_READ
Definition audiohook.h:49
@ AST_AUDIOHOOK_STATUS_DONE
Definition audiohook.h:45
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition dsp.c:1492
direction
struct stasis_message_type * ast_channel_talking_start(void)
Message type for a channel starting talking.
struct stasis_message_type * ast_channel_talking_stop(void)
Message type for a channel stopping talking.
struct stasis_message * ast_channel_blob_create_from_cache(const char *uniqueid, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
#define ast_verb(level,...)
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition json.c:612
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition json.h:87
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition stasis.c:1578
enum ast_audiohook_status status
Definition audiohook.h:108
enum ast_frame_type frametype
Abstract JSON element (object, array, string, int, ...).
struct timeval talking_start
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition time.h:159

References ao2_ref, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_STATUS_DONE, ast_channel_blob_create_from_cache(), ast_channel_datastore_find(), ast_channel_name(), ast_channel_talking_start(), ast_channel_talking_stop(), ast_channel_topic(), ast_channel_uniqueid(), ast_dsp_silence(), AST_FRAME_VOICE, ast_json_pack(), ast_json_unref(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, ast_datastore::data, talk_detect_params::dsp, talk_detect_params::dsp_silence_threshold, ast_frame::frametype, NULL, stasis_publish(), ast_audiohook::status, talk_detect_datastore, talk_detect_params::talking, and talk_detect_params::talking_start.

Referenced by set_talk_detect().

◆ talk_detect_fn_write()

static int talk_detect_fn_write ( struct ast_channel chan,
const char *  function,
char *  data,
const char *  value 
)
static

Definition at line 331 of file func_talkdetect.c.

332{
333 int res;
334
335 if (!chan) {
336 return -1;
337 }
338
339 if (ast_strlen_zero(data)) {
340 ast_log(AST_LOG_WARNING, "TALK_DETECT requires an argument\n");
341 return -1;
342 }
343
344 if (!strcasecmp(data, "set")) {
345 int dsp_silence_threshold = DEFAULT_SILENCE_THRESHOLD;
346 int dsp_talking_threshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
347
348 if (!ast_strlen_zero(value)) {
349 char *parse = ast_strdupa(value);
350
352 AST_APP_ARG(silence_threshold);
353 AST_APP_ARG(talking_threshold);
354 );
355
357
358 if (!ast_strlen_zero(args.silence_threshold)) {
359 if (sscanf(args.silence_threshold, "%30d", &dsp_silence_threshold) != 1) {
360 ast_log(AST_LOG_WARNING, "Failed to parse %s for dsp_silence_threshold\n",
361 args.silence_threshold);
362 return -1;
363 }
364
365 if (dsp_silence_threshold < 1) {
366 ast_log(AST_LOG_WARNING, "Invalid value %d for dsp_silence_threshold\n",
367 dsp_silence_threshold);
368 return -1;
369 }
370 }
371
372 if (!ast_strlen_zero(args.talking_threshold)) {
373 if (sscanf(args.talking_threshold, "%30d", &dsp_talking_threshold) != 1) {
374 ast_log(AST_LOG_WARNING, "Failed to parse %s for dsp_talking_threshold\n",
375 args.talking_threshold);
376 return -1;
377 }
378
379 if (dsp_talking_threshold < 1) {
380 ast_log(AST_LOG_WARNING, "Invalid value %d for dsp_talking_threshold\n",
381 dsp_talking_threshold);
382 return -1;
383 }
384 }
385 }
386
387 res = set_talk_detect(chan, dsp_silence_threshold, dsp_talking_threshold);
388 } else if (!strcasecmp(data, "remove")) {
389 res = remove_talk_detect(chan);
390 } else {
391 ast_log(AST_LOG_WARNING, "TALK_DETECT: unknown option %s\n", data);
392 res = -1;
393 }
394
395 return res;
396}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
@ THRESHOLD_SILENCE
Definition dsp.h:73
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition dsp.c:2013
static int set_talk_detect(struct ast_channel *chan, int dsp_silence_threshold, int dsp_talking_threshold)
#define DEFAULT_SILENCE_THRESHOLD
static int remove_talk_detect(struct ast_channel *chan)
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
static struct @519 args
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
int value
Definition syslog.c:37

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_dsp_get_threshold_from_settings(), ast_log, AST_LOG_WARNING, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), DEFAULT_SILENCE_THRESHOLD, talk_detect_params::dsp_silence_threshold, talk_detect_params::dsp_talking_threshold, remove_talk_detect(), set_talk_detect(), THRESHOLD_SILENCE, and value.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 405 of file func_talkdetect.c.

406{
407 int res = 0;
408
410
411 return res;
412}
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.

References ast_custom_function_unregister(), and talk_detect_function.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Talk detection dialplan function" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 424 of file func_talkdetect.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 424 of file func_talkdetect.c.

◆ talk_detect_datastore

const struct ast_datastore_info talk_detect_datastore
static
Initial value:
= {
.type = "talk_detect",
}
static void datastore_destroy_cb(void *data)

The channel datastore the function uses to store state.

Definition at line 167 of file func_talkdetect.c.

167 {
168 .type = "talk_detect",
169 .destroy = datastore_destroy_cb
170};

Referenced by remove_talk_detect(), set_talk_detect(), and talk_detect_audiohook_cb().

◆ talk_detect_function

struct ast_custom_function talk_detect_function
static
Initial value:
= {
.name = "TALK_DETECT",
}
static int talk_detect_fn_write(struct ast_channel *chan, const char *function, char *data, const char *value)

Definition of the TALK_DETECT function.

Definition at line 399 of file func_talkdetect.c.

399 {
400 .name = "TALK_DETECT",
401 .write = talk_detect_fn_write,
402};

Referenced by load_module(), and unload_module().