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...

Defines

#define DEFAULT_SILENCE_THRESHOLD   2500

Functions

static void __reg_module (void)
static void __unreg_module (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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static struct ast_module_infoast_module_info = &__mod_info
static 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 <mjordan@digium.com>

Definition in file func_talkdetect.c.


Define Documentation

#define DEFAULT_SILENCE_THRESHOLD   2500

Definition at line 117 of file func_talkdetect.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 405 of file func_talkdetect.c.

static void __unreg_module ( void   )  [static]

Definition at line 405 of file func_talkdetect.c.

static void datastore_destroy_cb ( void *  data  )  [static]

Definition at line 136 of file func_talkdetect.c.

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

00136                                              {
00137    struct talk_detect_params *td_params = data;
00138 
00139    ast_audiohook_destroy(&td_params->audiohook);
00140 
00141    if (td_params->dsp) {
00142       ast_dsp_free(td_params->dsp);
00143    }
00144    ast_free(data);
00145 }

static int load_module ( void   )  [static]

Definition at line 396 of file func_talkdetect.c.

References ast_custom_function_register, AST_MODULE_LOAD_FAILURE, and AST_MODULE_LOAD_SUCCESS.

00397 {
00398    int res = 0;
00399 
00400    res |= ast_custom_function_register(&talk_detect_function);
00401 
00402    return res ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS;
00403 }

static int remove_talk_detect ( struct ast_channel chan  )  [static]

Definition at line 231 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().

00232 {
00233    struct ast_datastore *datastore = NULL;
00234    struct talk_detect_params *td_params;
00235    SCOPED_CHANNELLOCK(chan_lock, chan);
00236 
00237    datastore = ast_channel_datastore_find(chan, &talk_detect_datastore, NULL);
00238    if (!datastore) {
00239       ast_log(AST_LOG_WARNING, "Cannot remove TALK_DETECT from %s: TALK_DETECT not currently enabled\n",
00240               ast_channel_name(chan));
00241       return -1;
00242    }
00243    td_params = datastore->data;
00244 
00245    if (ast_audiohook_remove(chan, &td_params->audiohook)) {
00246       ast_log(AST_LOG_WARNING, "Failed to remove TALK_DETECT audiohook from channel %s\n",
00247               ast_channel_name(chan));
00248       return -1;
00249    }
00250 
00251    if (ast_channel_datastore_remove(chan, datastore)) {
00252       ast_log(AST_LOG_WARNING, "Failed to remove TALK_DETECT datastore from channel %s\n",
00253               ast_channel_name(chan));
00254       return -1;
00255    }
00256    ast_datastore_free(datastore);
00257 
00258    return 0;
00259 }

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

Definition at line 262 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().

00263 {
00264    struct ast_datastore *datastore = NULL;
00265    struct talk_detect_params *td_params;
00266    SCOPED_CHANNELLOCK(chan_lock, chan);
00267 
00268    datastore = ast_channel_datastore_find(chan, &talk_detect_datastore, NULL);
00269    if (!datastore) {
00270       datastore = ast_datastore_alloc(&talk_detect_datastore, NULL);
00271       if (!datastore) {
00272          return -1;
00273       }
00274 
00275       td_params = ast_calloc(1, sizeof(*td_params));
00276       if (!td_params) {
00277          ast_datastore_free(datastore);
00278          return -1;
00279       }
00280 
00281       ast_audiohook_init(&td_params->audiohook,
00282                          AST_AUDIOHOOK_TYPE_MANIPULATE,
00283                          "TALK_DETECT",
00284                          AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
00285       td_params->audiohook.manipulate_callback = talk_detect_audiohook_cb;
00286       ast_set_flag(&td_params->audiohook, AST_AUDIOHOOK_TRIGGER_READ);
00287 
00288       td_params->dsp = ast_dsp_new_with_rate(ast_format_get_sample_rate(ast_channel_rawreadformat(chan)));
00289       if (!td_params->dsp) {
00290          ast_datastore_free(datastore);
00291          ast_free(td_params);
00292          return -1;
00293       }
00294       datastore->data = td_params;
00295 
00296       ast_channel_datastore_add(chan, datastore);
00297       ast_audiohook_attach(chan, &td_params->audiohook);
00298    } else {
00299       /* Talk detection already enabled; update existing settings */
00300       td_params = datastore->data;
00301    }
00302 
00303    td_params->dsp_talking_threshold = dsp_talking_threshold;
00304    td_params->dsp_silence_threshold = dsp_silence_threshold;
00305 
00306    ast_dsp_set_threshold(td_params->dsp, td_params->dsp_talking_threshold);
00307 
00308    return 0;
00309 }

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 161 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().

00162 {
00163    int total_silence;
00164    int update_talking = 0;
00165    struct ast_datastore *datastore;
00166    struct talk_detect_params *td_params;
00167    struct stasis_message *message;
00168 
00169    if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
00170       return 1;
00171    }
00172 
00173    if (direction != AST_AUDIOHOOK_DIRECTION_READ) {
00174       return 1;
00175    }
00176 
00177    if (frame->frametype != AST_FRAME_VOICE) {
00178       return 1;
00179    }
00180 
00181    if (!(datastore = ast_channel_datastore_find(chan, &talk_detect_datastore, NULL))) {
00182       return 1;
00183    }
00184    td_params = datastore->data;
00185 
00186    ast_dsp_silence(td_params->dsp, frame, &total_silence);
00187 
00188    if (total_silence < td_params->dsp_silence_threshold) {
00189       if (!td_params->talking) {
00190          update_talking = 1;
00191          td_params->talking_start = ast_tvnow();
00192       }
00193       td_params->talking = 1;
00194    } else {
00195       if (td_params->talking) {
00196          update_talking = 1;
00197       }
00198       td_params->talking = 0;
00199    }
00200 
00201    if (update_talking) {
00202       struct ast_json *blob = NULL;
00203 
00204       if (!td_params->talking) {
00205          int64_t diff_ms = ast_tvdiff_ms(ast_tvnow(), td_params->talking_start);
00206          diff_ms -= td_params->dsp_silence_threshold;
00207 
00208          blob = ast_json_pack("{s: i}", "duration", diff_ms);
00209          if (!blob) {
00210             return 1;
00211          }
00212       }
00213 
00214       ast_verb(4, "%s is now %s\n", ast_channel_name(chan),
00215                   td_params->talking ? "talking" : "silent");
00216       message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan),
00217                       td_params->talking ? ast_channel_talking_start() : ast_channel_talking_stop(),
00218                       blob);
00219       if (message) {
00220          stasis_publish(ast_channel_topic(chan), message);
00221          ao2_ref(message, -1);
00222       }
00223 
00224       ast_json_unref(blob);
00225    }
00226 
00227    return 1;
00228 }

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

Definition at line 312 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.

00313 {
00314    int res;
00315 
00316    if (!chan) {
00317       return -1;
00318    }
00319 
00320    if (ast_strlen_zero(data)) {
00321       ast_log(AST_LOG_WARNING, "TALK_DETECT requires an argument\n");
00322       return -1;
00323    }
00324 
00325    if (!strcasecmp(data, "set")) {
00326       int dsp_silence_threshold = DEFAULT_SILENCE_THRESHOLD;
00327       int dsp_talking_threshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
00328 
00329       if (!ast_strlen_zero(value)) {
00330          char *parse = ast_strdupa(value);
00331 
00332          AST_DECLARE_APP_ARGS(args,
00333             AST_APP_ARG(silence_threshold);
00334             AST_APP_ARG(talking_threshold);
00335          );
00336 
00337          AST_STANDARD_APP_ARGS(args, parse);
00338 
00339          if (!ast_strlen_zero(args.silence_threshold)) {
00340             if (sscanf(args.silence_threshold, "%30d", &dsp_silence_threshold) != 1) {
00341                ast_log(AST_LOG_WARNING, "Failed to parse %s for dsp_silence_threshold\n",
00342                        args.silence_threshold);
00343                return -1;
00344             }
00345 
00346             if (dsp_silence_threshold < 1) {
00347                ast_log(AST_LOG_WARNING, "Invalid value %d for dsp_silence_threshold\n",
00348                        dsp_silence_threshold);
00349                return -1;
00350             }
00351          }
00352 
00353          if (!ast_strlen_zero(args.talking_threshold)) {
00354             if (sscanf(args.talking_threshold, "%30d", &dsp_talking_threshold) != 1) {
00355                ast_log(AST_LOG_WARNING, "Failed to parse %s for dsp_talking_threshold\n",
00356                        args.talking_threshold);
00357                return -1;
00358             }
00359 
00360             if (dsp_talking_threshold < 1) {
00361                ast_log(AST_LOG_WARNING, "Invalid value %d for dsp_talking_threshold\n",
00362                        dsp_silence_threshold);
00363                return -1;
00364             }
00365          }
00366       }
00367 
00368       res = set_talk_detect(chan, dsp_silence_threshold, dsp_talking_threshold);
00369    } else if (!strcasecmp(data, "remove")) {
00370       res = remove_talk_detect(chan);
00371    } else {
00372       ast_log(AST_LOG_WARNING, "TALK_DETECT: unknown option %s\n", data);
00373       res = -1;
00374    }
00375 
00376    return res;
00377 }

static int unload_module ( void   )  [static]

Definition at line 386 of file func_talkdetect.c.

References ast_custom_function_unregister().

00387 {
00388    int res = 0;
00389 
00390    res |= ast_custom_function_unregister(&talk_detect_function);
00391 
00392    return res;
00393 }


Variable Documentation

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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, } [static]

Definition at line 405 of file func_talkdetect.c.

Definition at line 405 of file func_talkdetect.c.

Initial value:

 {
   .type = "talk_detect",
   .destroy = datastore_destroy_cb
}
The channel datastore the function uses to store state.

Definition at line 148 of file func_talkdetect.c.

Initial value:

 {
   .name = "TALK_DETECT",
   .write = talk_detect_fn_write,
}
Definition of the TALK_DETECT function.

Definition at line 380 of file func_talkdetect.c.


Generated on Thu Apr 16 06:31:27 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6