Asterisk - The Open Source Telephony Project  18.5.0
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 = "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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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. More...
 
static struct ast_custom_function talk_detect_function
 Definition of the TALK_DETECT function. More...
 

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 115 of file func_talkdetect.c.

Referenced by talk_detect_fn_write().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 403 of file func_talkdetect.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 403 of file func_talkdetect.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 403 of file func_talkdetect.c.

◆ datastore_destroy_cb()

static void datastore_destroy_cb ( void *  data)
static

Definition at line 134 of file func_talkdetect.c.

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

134  {
135  struct talk_detect_params *td_params = data;
136 
137  ast_audiohook_destroy(&td_params->audiohook);
138 
139  if (td_params->dsp) {
140  ast_dsp_free(td_params->dsp);
141  }
142  ast_free(data);
143 }
struct ast_dsp * dsp
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
Definition: audiohook.c:133
Private data structure used with the function's datastore.
struct ast_audiohook audiohook
#define ast_free(a)
Definition: astmm.h:182

◆ load_module()

static int load_module ( void  )
static

Definition at line 394 of file func_talkdetect.c.

References ast_custom_function_register, AST_MODULE_LOAD_DECLINE, and AST_MODULE_LOAD_SUCCESS.

395 {
396  int res = 0;
397 
399 
401 }
static struct ast_custom_function talk_detect_function
Definition of the TALK_DETECT function.
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:1508

◆ remove_talk_detect()

static int remove_talk_detect ( struct ast_channel chan)
static

Definition at line 229 of file func_talkdetect.c.

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, and SCOPED_CHANNELLOCK.

Referenced by talk_detect_fn_write().

230 {
231  struct ast_datastore *datastore = NULL;
232  struct talk_detect_params *td_params;
233  SCOPED_CHANNELLOCK(chan_lock, chan);
234 
236  if (!datastore) {
237  ast_log(AST_LOG_WARNING, "Cannot remove TALK_DETECT from %s: TALK_DETECT not currently enabled\n",
238  ast_channel_name(chan));
239  return -1;
240  }
241  td_params = datastore->data;
242 
243  if (ast_audiohook_remove(chan, &td_params->audiohook)) {
244  ast_log(AST_LOG_WARNING, "Failed to remove TALK_DETECT audiohook from channel %s\n",
245  ast_channel_name(chan));
246  return -1;
247  }
248 
249  if (ast_channel_datastore_remove(chan, datastore)) {
250  ast_log(AST_LOG_WARNING, "Failed to remove TALK_DETECT datastore from channel %s\n",
251  ast_channel_name(chan));
252  return -1;
253  }
254  ast_datastore_free(datastore);
255 
256  return 0;
257 }
int ast_audiohook_remove(struct ast_channel *chan, struct ast_audiohook *audiohook)
Remove an audiohook from a specified channel.
Definition: audiohook.c:764
#define AST_LOG_WARNING
Definition: logger.h:279
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define ast_log
Definition: astobj2.c:42
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
Private data structure used with the function's datastore.
struct ast_audiohook audiohook
static const struct ast_datastore_info talk_detect_datastore
The channel datastore the function uses to store state.
void * data
Definition: datastore.h:70
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:2399

◆ set_talk_detect()

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

Definition at line 260 of file func_talkdetect.c.

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, and talk_detect_audiohook_cb().

Referenced by talk_detect_fn_write().

261 {
262  struct ast_datastore *datastore = NULL;
263  struct talk_detect_params *td_params;
264  SCOPED_CHANNELLOCK(chan_lock, chan);
265 
267  if (!datastore) {
269  if (!datastore) {
270  return -1;
271  }
272 
273  td_params = ast_calloc(1, sizeof(*td_params));
274  if (!td_params) {
275  ast_datastore_free(datastore);
276  return -1;
277  }
278 
279  ast_audiohook_init(&td_params->audiohook,
281  "TALK_DETECT",
285 
287  if (!td_params->dsp) {
288  ast_datastore_free(datastore);
289  ast_free(td_params);
290  return -1;
291  }
292  datastore->data = td_params;
293 
294  ast_channel_datastore_add(chan, datastore);
295  ast_audiohook_attach(chan, &td_params->audiohook);
296  } else {
297  /* Talk detection already enabled; update existing settings */
298  td_params = datastore->data;
299  }
300 
303 
304  ast_dsp_set_threshold(td_params->dsp, td_params->dsp_talking_threshold);
305 
306  return 0;
307 }
struct ast_dsp * dsp
#define ast_set_flag(p, flag)
Definition: utils.h:70
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition: audiohook.c:501
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
ast_audiohook_manipulate_callback manipulate_callback
Definition: audiohook.h:117
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:108
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
Private data structure used with the function's datastore.
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:1775
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
struct ast_audiohook audiohook
static int talk_detect_audiohook_cb(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
static const struct ast_datastore_info talk_detect_datastore
The channel datastore the function uses to store state.
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void * data
Definition: datastore.h:70
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
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:1750
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390

◆ 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 159 of file func_talkdetect.c.

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_params::talking, and talk_detect_params::talking_start.

Referenced by set_talk_detect().

160 {
161  int total_silence;
162  int update_talking = 0;
163  struct ast_datastore *datastore;
164  struct talk_detect_params *td_params;
165  struct stasis_message *message;
166 
167  if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
168  return 1;
169  }
170 
172  return 1;
173  }
174 
175  if (frame->frametype != AST_FRAME_VOICE) {
176  return 1;
177  }
178 
179  if (!(datastore = ast_channel_datastore_find(chan, &talk_detect_datastore, NULL))) {
180  return 1;
181  }
182  td_params = datastore->data;
183 
184  ast_dsp_silence(td_params->dsp, frame, &total_silence);
185 
186  if (total_silence < td_params->dsp_silence_threshold) {
187  if (!td_params->talking) {
188  update_talking = 1;
189  td_params->talking_start = ast_tvnow();
190  }
191  td_params->talking = 1;
192  } else {
193  if (td_params->talking) {
194  update_talking = 1;
195  }
196  td_params->talking = 0;
197  }
198 
199  if (update_talking) {
200  struct ast_json *blob = NULL;
201 
202  if (!td_params->talking) {
203  int64_t diff_ms = ast_tvdiff_ms(ast_tvnow(), td_params->talking_start);
204  diff_ms -= td_params->dsp_silence_threshold;
205 
206  blob = ast_json_pack("{s: I}", "duration", (ast_json_int_t)diff_ms);
207  if (!blob) {
208  return 1;
209  }
210  }
211 
212  ast_verb(4, "%s is now %s\n", ast_channel_name(chan),
213  td_params->talking ? "talking" : "silent");
216  blob);
217  if (message) {
218  stasis_publish(ast_channel_topic(chan), message);
219  ao2_ref(message, -1);
220  }
221 
222  ast_json_unref(blob);
223  }
224 
225  return 1;
226 }
struct stasis_message_type * ast_channel_talking_stop(void)
Message type for a channel stopping talking.
struct ast_dsp * dsp
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
struct stasis_message_type * ast_channel_talking_start(void)
Message type for a channel starting talking.
#define ast_verb(level,...)
Definition: logger.h:463
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Private data structure used with the function&#39;s datastore.
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
static const struct ast_datastore_info talk_detect_datastore
The channel datastore the function uses to store state.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
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.
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition: dsp.c:1483
void * data
Definition: datastore.h:70
const char * ast_channel_name(const struct ast_channel *chan)
Abstract JSON element (object, array, string, int, ...).
enum ast_audiohook_status status
Definition: audiohook.h:107
enum ast_frame_type frametype
direction
struct timeval talking_start

◆ 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 310 of file func_talkdetect.c.

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, parse(), remove_talk_detect(), set_talk_detect(), and THRESHOLD_SILENCE.

311 {
312  int res;
313 
314  if (!chan) {
315  return -1;
316  }
317 
318  if (ast_strlen_zero(data)) {
319  ast_log(AST_LOG_WARNING, "TALK_DETECT requires an argument\n");
320  return -1;
321  }
322 
323  if (!strcasecmp(data, "set")) {
324  int dsp_silence_threshold = DEFAULT_SILENCE_THRESHOLD;
325  int dsp_talking_threshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
326 
327  if (!ast_strlen_zero(value)) {
328  char *parse = ast_strdupa(value);
329 
331  AST_APP_ARG(silence_threshold);
332  AST_APP_ARG(talking_threshold);
333  );
334 
335  AST_STANDARD_APP_ARGS(args, parse);
336 
337  if (!ast_strlen_zero(args.silence_threshold)) {
338  if (sscanf(args.silence_threshold, "%30d", &dsp_silence_threshold) != 1) {
339  ast_log(AST_LOG_WARNING, "Failed to parse %s for dsp_silence_threshold\n",
340  args.silence_threshold);
341  return -1;
342  }
343 
344  if (dsp_silence_threshold < 1) {
345  ast_log(AST_LOG_WARNING, "Invalid value %d for dsp_silence_threshold\n",
346  dsp_silence_threshold);
347  return -1;
348  }
349  }
350 
351  if (!ast_strlen_zero(args.talking_threshold)) {
352  if (sscanf(args.talking_threshold, "%30d", &dsp_talking_threshold) != 1) {
353  ast_log(AST_LOG_WARNING, "Failed to parse %s for dsp_talking_threshold\n",
354  args.talking_threshold);
355  return -1;
356  }
357 
358  if (dsp_talking_threshold < 1) {
359  ast_log(AST_LOG_WARNING, "Invalid value %d for dsp_talking_threshold\n",
360  dsp_silence_threshold);
361  return -1;
362  }
363  }
364  }
365 
366  res = set_talk_detect(chan, dsp_silence_threshold, dsp_talking_threshold);
367  } else if (!strcasecmp(data, "remove")) {
368  res = remove_talk_detect(chan);
369  } else {
370  ast_log(AST_LOG_WARNING, "TALK_DETECT: unknown option %s\n", data);
371  res = -1;
372  }
373 
374  return res;
375 }
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define AST_LOG_WARNING
Definition: logger.h:279
const char * args
int value
Definition: syslog.c:37
#define DEFAULT_SILENCE_THRESHOLD
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
static int set_talk_detect(struct ast_channel *chan, int dsp_silence_threshold, int dsp_talking_threshold)
static int remove_talk_detect(struct ast_channel *chan)
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:1996
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 384 of file func_talkdetect.c.

References ast_custom_function_unregister().

385 {
386  int res = 0;
387 
389 
390  return res;
391 }
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static struct ast_custom_function talk_detect_function
Definition of the 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 = "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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 403 of file func_talkdetect.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 403 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 146 of file func_talkdetect.c.

◆ 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 378 of file func_talkdetect.c.