Create a centralized configuration option for silencethreshold
(closes issue #11236) Reported by: philipps Patches: 20080218__bug11236.diff.txt uploaded by Corydon76 (license 14) Tested by: philipps git-svn-id: http://svn.digium.com/svn/asterisk/trunk@106072 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
6f39909904
commit
198829f2db
4
CHANGES
4
CHANGES
|
@ -175,7 +175,7 @@ Skinny changes
|
||||||
* Proper codec support in chan_skinny.
|
* Proper codec support in chan_skinny.
|
||||||
* Added settings for IP and Ethernet QoS requests
|
* Added settings for IP and Ethernet QoS requests
|
||||||
|
|
||||||
|
MGCP changes
|
||||||
------------
|
------------
|
||||||
* Added separate settings for media QoS in mgcp.conf
|
* Added separate settings for media QoS in mgcp.conf
|
||||||
|
|
||||||
|
@ -387,6 +387,8 @@ Other Dialplan Application Changes
|
||||||
* The ChannelRedirect application no longer exits the dialplan if the given channel
|
* The ChannelRedirect application no longer exits the dialplan if the given channel
|
||||||
does not exist. It will now set the CHANNELREDIRECT_STATUS variable to SUCCESS upon success
|
does not exist. It will now set the CHANNELREDIRECT_STATUS variable to SUCCESS upon success
|
||||||
or NOCHANNEL if the given channel was not found.
|
or NOCHANNEL if the given channel was not found.
|
||||||
|
* The silencethreshold setting that was previously configurable in multiple
|
||||||
|
applications is now settable globally via dsp.conf.
|
||||||
|
|
||||||
Music On Hold Changes
|
Music On Hold Changes
|
||||||
---------------------
|
---------------------
|
||||||
|
|
|
@ -56,6 +56,9 @@ Core:
|
||||||
* The concise versions of various CLI commands are now deprecated. We recommend
|
* The concise versions of various CLI commands are now deprecated. We recommend
|
||||||
using the manager interface (AMI) for application integration with Asterisk.
|
using the manager interface (AMI) for application integration with Asterisk.
|
||||||
|
|
||||||
|
* The silencethreshold used for various applications is now settable via a
|
||||||
|
centralized config option in dsp.conf.
|
||||||
|
|
||||||
Voicemail:
|
Voicemail:
|
||||||
|
|
||||||
* The voicemail configuration values 'maxmessage' and 'minmessage' have
|
* The voicemail configuration values 'maxmessage' and 'minmessage' have
|
||||||
|
|
|
@ -371,6 +371,8 @@ static int load_config(int reload)
|
||||||
struct ast_variable *var = NULL;
|
struct ast_variable *var = NULL;
|
||||||
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
|
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
|
||||||
|
|
||||||
|
dfltSilenceThreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
|
||||||
|
|
||||||
if (!(cfg = ast_config_load("amd.conf", config_flags))) {
|
if (!(cfg = ast_config_load("amd.conf", config_flags))) {
|
||||||
ast_log(LOG_ERROR, "Configuration file amd.conf missing.\n");
|
ast_log(LOG_ERROR, "Configuration file amd.conf missing.\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -60,6 +60,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||||
#include "asterisk/privacy.h"
|
#include "asterisk/privacy.h"
|
||||||
#include "asterisk/stringfields.h"
|
#include "asterisk/stringfields.h"
|
||||||
#include "asterisk/global_datastores.h"
|
#include "asterisk/global_datastores.h"
|
||||||
|
#include "asterisk/dsp.h"
|
||||||
|
|
||||||
static char *app = "Dial";
|
static char *app = "Dial";
|
||||||
|
|
||||||
|
@ -1115,6 +1116,7 @@ static int setup_privacy_args(struct privacy_args *pa,
|
||||||
char callerid[60];
|
char callerid[60];
|
||||||
int res;
|
int res;
|
||||||
char *l;
|
char *l;
|
||||||
|
int silencethreshold;
|
||||||
|
|
||||||
if (!ast_strlen_zero(chan->cid.cid_num)) {
|
if (!ast_strlen_zero(chan->cid.cid_num)) {
|
||||||
l = ast_strdupa(chan->cid.cid_num);
|
l = ast_strdupa(chan->cid.cid_num);
|
||||||
|
@ -1188,8 +1190,9 @@ static int setup_privacy_args(struct privacy_args *pa,
|
||||||
"At the tone, please say your name:"
|
"At the tone, please say your name:"
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
|
||||||
ast_answer(chan);
|
ast_answer(chan);
|
||||||
res = ast_play_and_record(chan, "priv-recordintro", pa->privintro, 4, "gsm", &duration, 128, 2000, 0); /* NOTE: I've reduced the total time to 4 sec */
|
res = ast_play_and_record(chan, "priv-recordintro", pa->privintro, 4, "gsm", &duration, silencethreshold, 2000, 0); /* NOTE: I've reduced the total time to 4 sec */
|
||||||
/* don't think we'll need a lock removed, we took care of
|
/* don't think we'll need a lock removed, we took care of
|
||||||
conflicts by naming the pa.privintro file */
|
conflicts by naming the pa.privintro file */
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
|
|
|
@ -55,6 +55,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||||
#include "asterisk/utils.h"
|
#include "asterisk/utils.h"
|
||||||
#include "asterisk/causes.h"
|
#include "asterisk/causes.h"
|
||||||
#include "asterisk/astdb.h"
|
#include "asterisk/astdb.h"
|
||||||
|
#include "asterisk/dsp.h"
|
||||||
#include "asterisk/app.h"
|
#include "asterisk/app.h"
|
||||||
|
|
||||||
static char *app = "FollowMe";
|
static char *app = "FollowMe";
|
||||||
|
@ -130,7 +131,7 @@ struct findme_user {
|
||||||
int ynidx;
|
int ynidx;
|
||||||
long digts;
|
long digts;
|
||||||
int cleared;
|
int cleared;
|
||||||
AST_LIST_ENTRY(findme_user) entry;
|
AST_LIST_ENTRY(findme_user) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -183,7 +184,6 @@ static void free_numbers(struct call_followme *f)
|
||||||
/* Free the whitelisted number */
|
/* Free the whitelisted number */
|
||||||
ast_free(prev);
|
ast_free(prev);
|
||||||
AST_LIST_HEAD_INIT_NOLOCK(&f->wlnumbers);
|
AST_LIST_HEAD_INIT_NOLOCK(&f->wlnumbers);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -258,7 +258,6 @@ static struct number *create_followme_number(char *number, int timeout, int numo
|
||||||
{
|
{
|
||||||
struct number *cur;
|
struct number *cur;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
||||||
|
|
||||||
if (!(cur = ast_calloc(1, sizeof(*cur))))
|
if (!(cur = ast_calloc(1, sizeof(*cur))))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -284,7 +283,7 @@ static int reload_followme(int reload)
|
||||||
char numberstr[90];
|
char numberstr[90];
|
||||||
int timeout;
|
int timeout;
|
||||||
char *timeoutstr;
|
char *timeoutstr;
|
||||||
int numorder;
|
int numorder;
|
||||||
const char *takecallstr;
|
const char *takecallstr;
|
||||||
const char *declinecallstr;
|
const char *declinecallstr;
|
||||||
const char *tmpstr;
|
const char *tmpstr;
|
||||||
|
@ -307,7 +306,7 @@ static int reload_followme(int reload)
|
||||||
}
|
}
|
||||||
|
|
||||||
featuredigittostr = ast_variable_retrieve(cfg, "general", "featuredigittimeout");
|
featuredigittostr = ast_variable_retrieve(cfg, "general", "featuredigittimeout");
|
||||||
|
|
||||||
if (!ast_strlen_zero(featuredigittostr)) {
|
if (!ast_strlen_zero(featuredigittostr)) {
|
||||||
if (!sscanf(featuredigittostr, "%d", &featuredigittimeout))
|
if (!sscanf(featuredigittostr, "%d", &featuredigittimeout))
|
||||||
featuredigittimeout = 5000;
|
featuredigittimeout = 5000;
|
||||||
|
@ -316,7 +315,7 @@ static int reload_followme(int reload)
|
||||||
takecallstr = ast_variable_retrieve(cfg, "general", "takecall");
|
takecallstr = ast_variable_retrieve(cfg, "general", "takecall");
|
||||||
if (!ast_strlen_zero(takecallstr))
|
if (!ast_strlen_zero(takecallstr))
|
||||||
ast_copy_string(takecall, takecallstr, sizeof(takecall));
|
ast_copy_string(takecall, takecallstr, sizeof(takecall));
|
||||||
|
|
||||||
declinecallstr = ast_variable_retrieve(cfg, "general", "declinecall");
|
declinecallstr = ast_variable_retrieve(cfg, "general", "declinecall");
|
||||||
if (!ast_strlen_zero(declinecallstr))
|
if (!ast_strlen_zero(declinecallstr))
|
||||||
ast_copy_string(nextindp, declinecallstr, sizeof(nextindp));
|
ast_copy_string(nextindp, declinecallstr, sizeof(nextindp));
|
||||||
|
@ -369,7 +368,7 @@ static int reload_followme(int reload)
|
||||||
/* Totally fail if we fail to find/create an entry */
|
/* Totally fail if we fail to find/create an entry */
|
||||||
if (!f)
|
if (!f)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!new)
|
if (!new)
|
||||||
ast_mutex_lock(&f->lock);
|
ast_mutex_lock(&f->lock);
|
||||||
/* Re-initialize the profile */
|
/* Re-initialize the profile */
|
||||||
|
@ -399,8 +398,8 @@ static int reload_followme(int reload)
|
||||||
timeout = 25;
|
timeout = 25;
|
||||||
numorder = 0;
|
numorder = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!numorder) {
|
if (!numorder) {
|
||||||
idx = 1;
|
idx = 1;
|
||||||
AST_LIST_TRAVERSE(&f->numbers, nm, entry)
|
AST_LIST_TRAVERSE(&f->numbers, nm, entry)
|
||||||
idx++;
|
idx++;
|
||||||
|
@ -414,7 +413,7 @@ static int reload_followme(int reload)
|
||||||
}
|
}
|
||||||
var = var->next;
|
var = var->next;
|
||||||
} /* End while(var) loop */
|
} /* End while(var) loop */
|
||||||
|
|
||||||
if (!new)
|
if (!new)
|
||||||
ast_mutex_unlock(&f->lock);
|
ast_mutex_unlock(&f->lock);
|
||||||
else
|
else
|
||||||
|
@ -431,7 +430,7 @@ static int reload_followme(int reload)
|
||||||
static void clear_caller(struct findme_user *tmpuser)
|
static void clear_caller(struct findme_user *tmpuser)
|
||||||
{
|
{
|
||||||
struct ast_channel *outbound;
|
struct ast_channel *outbound;
|
||||||
|
|
||||||
if (tmpuser && tmpuser->ochan && tmpuser->state >= 0) {
|
if (tmpuser && tmpuser->ochan && tmpuser->state >= 0) {
|
||||||
outbound = tmpuser->ochan;
|
outbound = tmpuser->ochan;
|
||||||
if (!outbound->cdr) {
|
if (!outbound->cdr) {
|
||||||
|
@ -460,12 +459,11 @@ static void clear_caller(struct findme_user *tmpuser)
|
||||||
static void clear_calling_tree(struct findme_user_listptr *findme_user_list)
|
static void clear_calling_tree(struct findme_user_listptr *findme_user_list)
|
||||||
{
|
{
|
||||||
struct findme_user *tmpuser;
|
struct findme_user *tmpuser;
|
||||||
|
|
||||||
AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
|
AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
|
||||||
clear_caller(tmpuser);
|
clear_caller(tmpuser);
|
||||||
tmpuser->cleared = 1;
|
tmpuser->cleared = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -489,29 +487,29 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
|
||||||
/* ------------ wait_for_winner_channel start --------------- */
|
/* ------------ wait_for_winner_channel start --------------- */
|
||||||
|
|
||||||
callfromname = ast_strdupa(tpargs->callfromprompt);
|
callfromname = ast_strdupa(tpargs->callfromprompt);
|
||||||
pressbuttonname = ast_strdupa(tpargs->optionsprompt);
|
pressbuttonname = ast_strdupa(tpargs->optionsprompt);
|
||||||
|
|
||||||
if (AST_LIST_EMPTY(findme_user_list)) {
|
if (AST_LIST_EMPTY(findme_user_list)) {
|
||||||
ast_verb(3, "couldn't reach at this number.\n");
|
ast_verb(3, "couldn't reach at this number.\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!caller) {
|
if (!caller) {
|
||||||
ast_verb(3, "Original caller hungup. Cleanup.\n");
|
ast_verb(3, "Original caller hungup. Cleanup.\n");
|
||||||
clear_calling_tree(findme_user_list);
|
clear_calling_tree(findme_user_list);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
totalwait = nm->timeout * 1000;
|
totalwait = nm->timeout * 1000;
|
||||||
|
|
||||||
while (!ctstatus) {
|
while (!ctstatus) {
|
||||||
to = 1000;
|
to = 1000;
|
||||||
pos = 1;
|
pos = 1;
|
||||||
livechannels = 0;
|
livechannels = 0;
|
||||||
watchers[0] = caller;
|
watchers[0] = caller;
|
||||||
|
|
||||||
dg = 0;
|
dg = 0;
|
||||||
winner = NULL;
|
winner = NULL;
|
||||||
AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
|
AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
|
||||||
if (tmpuser->state >= 0 && tmpuser->ochan) {
|
if (tmpuser->state >= 0 && tmpuser->ochan) {
|
||||||
if (tmpuser->state == 3)
|
if (tmpuser->state == 3)
|
||||||
|
@ -526,7 +524,7 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
|
||||||
} else {
|
} else {
|
||||||
ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
|
ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tmpuser->state = 2;
|
tmpuser->state = 2;
|
||||||
tmpuser->digts = 0;
|
tmpuser->digts = 0;
|
||||||
|
@ -566,7 +564,6 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
|
||||||
tmpuser->ynidx = 0;
|
tmpuser->ynidx = 0;
|
||||||
if (!ast_streamfile(tmpuser->ochan, pressbuttonname, tmpuser->ochan->language)) {
|
if (!ast_streamfile(tmpuser->ochan, pressbuttonname, tmpuser->ochan->language)) {
|
||||||
tmpuser->state = 3;
|
tmpuser->state = 3;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -580,7 +577,7 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
|
||||||
livechannels++;
|
livechannels++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpto = to;
|
tmpto = to;
|
||||||
if (to < 0) {
|
if (to < 0) {
|
||||||
to = 1000;
|
to = 1000;
|
||||||
|
@ -590,7 +587,7 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
|
||||||
winner = ast_waitfor_n(watchers, pos, &to);
|
winner = ast_waitfor_n(watchers, pos, &to);
|
||||||
tmpto -= to;
|
tmpto -= to;
|
||||||
totalwait -= tmpto;
|
totalwait -= tmpto;
|
||||||
wtd = to;
|
wtd = to;
|
||||||
if (totalwait <= 0) {
|
if (totalwait <= 0) {
|
||||||
ast_verb(3, "We've hit our timeout for this step. Drop everyone and move on to the next one. %ld\n", totalwait);
|
ast_verb(3, "We've hit our timeout for this step. Drop everyone and move on to the next one. %ld\n", totalwait);
|
||||||
clear_calling_tree(findme_user_list);
|
clear_calling_tree(findme_user_list);
|
||||||
|
@ -631,8 +628,8 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
|
||||||
ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
|
ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
|
||||||
ast_frfree(f);
|
ast_frfree(f);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tmpuser->state = 2;
|
tmpuser->state = 2;
|
||||||
if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, tmpuser->ochan->language))
|
if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, tmpuser->ochan->language))
|
||||||
ast_sched_runq(tmpuser->ochan->sched);
|
ast_sched_runq(tmpuser->ochan->sched);
|
||||||
|
@ -693,18 +690,18 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
|
||||||
if (!strcmp(tmpuser->yn, tpargs->takecall)) {
|
if (!strcmp(tmpuser->yn, tpargs->takecall)) {
|
||||||
ast_debug(1, "Match to take the call!\n");
|
ast_debug(1, "Match to take the call!\n");
|
||||||
ast_frfree(f);
|
ast_frfree(f);
|
||||||
return tmpuser->ochan;
|
return tmpuser->ochan;
|
||||||
}
|
}
|
||||||
if (!strcmp(tmpuser->yn, tpargs->nextindp)) {
|
if (!strcmp(tmpuser->yn, tpargs->nextindp)) {
|
||||||
ast_debug(1, "Next in dial plan step requested.\n");
|
ast_debug(1, "Next in dial plan step requested.\n");
|
||||||
*status = 1;
|
*status = 1;
|
||||||
ast_frfree(f);
|
ast_frfree(f);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_frfree(f);
|
ast_frfree(f);
|
||||||
} else {
|
} else {
|
||||||
if (winner) {
|
if (winner) {
|
||||||
|
@ -723,12 +720,12 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else
|
} else
|
||||||
ast_debug(1, "timed out waiting for action\n");
|
ast_debug(1, "timed out waiting for action\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- WAIT FOR WINNER NUMBER END! -----------*/
|
/* --- WAIT FOR WINNER NUMBER END! -----------*/
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -748,7 +745,7 @@ static void findmeexec(struct fm_args *tpargs)
|
||||||
struct findme_user_listptr *findme_user_list;
|
struct findme_user_listptr *findme_user_list;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
findme_user_list = ast_calloc(1, sizeof(*findme_user_list));
|
findme_user_list = ast_calloc(1, sizeof(*findme_user_list));
|
||||||
AST_LIST_HEAD_INIT_NOLOCK(findme_user_list);
|
AST_LIST_HEAD_INIT_NOLOCK(findme_user_list);
|
||||||
|
|
||||||
/* We're going to figure out what the longest possible string of digits to collect is */
|
/* We're going to figure out what the longest possible string of digits to collect is */
|
||||||
|
@ -782,14 +779,14 @@ static void findmeexec(struct fm_args *tpargs)
|
||||||
sprintf(dialarg, "%s", number);
|
sprintf(dialarg, "%s", number);
|
||||||
else
|
else
|
||||||
sprintf(dialarg, "%s@%s", number, tpargs->context);
|
sprintf(dialarg, "%s@%s", number, tpargs->context);
|
||||||
|
|
||||||
tmpuser = ast_calloc(1, sizeof(*tmpuser));
|
tmpuser = ast_calloc(1, sizeof(*tmpuser));
|
||||||
if (!tmpuser) {
|
if (!tmpuser) {
|
||||||
ast_log(LOG_WARNING, "Out of memory!\n");
|
ast_log(LOG_WARNING, "Out of memory!\n");
|
||||||
ast_free(findme_user_list);
|
ast_free(findme_user_list);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
outbound = ast_request("Local", ast_best_codec(caller->nativeformats), dialarg, &dg);
|
outbound = ast_request("Local", ast_best_codec(caller->nativeformats), dialarg, &dg);
|
||||||
if (outbound) {
|
if (outbound) {
|
||||||
ast_set_callerid(outbound, caller->cid.cid_num, caller->cid.cid_name, caller->cid.cid_num);
|
ast_set_callerid(outbound, caller->cid.cid_num, caller->cid.cid_name, caller->cid.cid_num);
|
||||||
|
@ -824,19 +821,17 @@ static void findmeexec(struct fm_args *tpargs)
|
||||||
outbound = NULL;
|
outbound = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ast_log(LOG_WARNING, "Unable to allocate a channel for Local/%s cause: %s\n", dialarg, ast_cause2str(dg));
|
ast_log(LOG_WARNING, "Unable to allocate a channel for Local/%s cause: %s\n", dialarg, ast_cause2str(dg));
|
||||||
|
|
||||||
number = rest;
|
number = rest;
|
||||||
} while (number);
|
} while (number);
|
||||||
|
|
||||||
status = 0;
|
status = 0;
|
||||||
if (!AST_LIST_EMPTY(findme_user_list))
|
if (!AST_LIST_EMPTY(findme_user_list))
|
||||||
winner = wait_for_winner(findme_user_list, nm, caller, tpargs->namerecloc, &status, tpargs);
|
winner = wait_for_winner(findme_user_list, nm, caller, tpargs->namerecloc, &status, tpargs);
|
||||||
|
|
||||||
|
|
||||||
while ((fmuser = AST_LIST_REMOVE_HEAD(findme_user_list, entry))) {
|
while ((fmuser = AST_LIST_REMOVE_HEAD(findme_user_list, entry))) {
|
||||||
if (!fmuser->cleared && fmuser->ochan != winner)
|
if (!fmuser->cleared && fmuser->ochan != winner)
|
||||||
clear_caller(fmuser);
|
clear_caller(fmuser);
|
||||||
|
@ -845,21 +840,21 @@ static void findmeexec(struct fm_args *tpargs)
|
||||||
|
|
||||||
fmuser = NULL;
|
fmuser = NULL;
|
||||||
tmpuser = NULL;
|
tmpuser = NULL;
|
||||||
headuser = NULL;
|
headuser = NULL;
|
||||||
if (winner)
|
if (winner)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!caller) {
|
if (!caller) {
|
||||||
tpargs->status = 1;
|
tpargs->status = 1;
|
||||||
ast_free(findme_user_list);
|
ast_free(findme_user_list);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx++;
|
idx++;
|
||||||
AST_LIST_TRAVERSE(&tpargs->cnumbers, nm, entry)
|
AST_LIST_TRAVERSE(&tpargs->cnumbers, nm, entry) {
|
||||||
if (nm->order == idx)
|
if (nm->order == idx)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast_free(findme_user_list);
|
ast_free(findme_user_list);
|
||||||
if (!winner)
|
if (!winner)
|
||||||
|
@ -869,9 +864,7 @@ static void findmeexec(struct fm_args *tpargs)
|
||||||
tpargs->outbound = winner;
|
tpargs->outbound = winner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int app_exec(struct ast_channel *chan, void *data)
|
static int app_exec(struct ast_channel *chan, void *data)
|
||||||
|
@ -887,7 +880,6 @@ static int app_exec(struct ast_channel *chan, void *data)
|
||||||
struct ast_channel *caller;
|
struct ast_channel *caller;
|
||||||
struct ast_channel *outbound;
|
struct ast_channel *outbound;
|
||||||
static char toast[80];
|
static char toast[80];
|
||||||
|
|
||||||
AST_DECLARE_APP_ARGS(args,
|
AST_DECLARE_APP_ARGS(args,
|
||||||
AST_APP_ARG(followmeid);
|
AST_APP_ARG(followmeid);
|
||||||
AST_APP_ARG(options);
|
AST_APP_ARG(options);
|
||||||
|
@ -897,7 +889,7 @@ static int app_exec(struct ast_channel *chan, void *data)
|
||||||
ast_log(LOG_WARNING, "%s requires an argument (followmeid)\n", app);
|
ast_log(LOG_WARNING, "%s requires an argument (followmeid)\n", app);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(argstr = ast_strdupa((char *)data))) {
|
if (!(argstr = ast_strdupa((char *)data))) {
|
||||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -916,7 +908,7 @@ static int app_exec(struct ast_channel *chan, void *data)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
AST_RWLIST_UNLOCK(&followmes);
|
AST_RWLIST_UNLOCK(&followmes);
|
||||||
|
|
||||||
ast_debug(1, "New profile %s.\n", args.followmeid);
|
ast_debug(1, "New profile %s.\n", args.followmeid);
|
||||||
|
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
@ -927,7 +919,7 @@ static int app_exec(struct ast_channel *chan, void *data)
|
||||||
/* XXX TODO: Reinsert the db check value to see whether or not follow-me is on or off */
|
/* XXX TODO: Reinsert the db check value to see whether or not follow-me is on or off */
|
||||||
if (args.options)
|
if (args.options)
|
||||||
ast_app_parse_options(followme_opts, &targs.followmeflags, NULL, args.options);
|
ast_app_parse_options(followme_opts, &targs.followmeflags, NULL, args.options);
|
||||||
|
|
||||||
/* Lock the profile lock and copy out everything we need to run with before unlocking it again */
|
/* Lock the profile lock and copy out everything we need to run with before unlocking it again */
|
||||||
ast_mutex_lock(&f->lock);
|
ast_mutex_lock(&f->lock);
|
||||||
targs.mohclass = ast_strdupa(f->moh);
|
targs.mohclass = ast_strdupa(f->moh);
|
||||||
|
@ -948,38 +940,38 @@ static int app_exec(struct ast_channel *chan, void *data)
|
||||||
AST_LIST_INSERT_TAIL(&targs.cnumbers, newnm, entry);
|
AST_LIST_INSERT_TAIL(&targs.cnumbers, newnm, entry);
|
||||||
}
|
}
|
||||||
ast_mutex_unlock(&f->lock);
|
ast_mutex_unlock(&f->lock);
|
||||||
|
|
||||||
if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_STATUSMSG))
|
if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_STATUSMSG))
|
||||||
ast_stream_and_wait(chan, targs.statusprompt, "");
|
ast_stream_and_wait(chan, targs.statusprompt, "");
|
||||||
|
|
||||||
snprintf(namerecloc,sizeof(namerecloc),"%s/followme.%s",ast_config_AST_SPOOL_DIR,chan->uniqueid);
|
snprintf(namerecloc,sizeof(namerecloc),"%s/followme.%s",ast_config_AST_SPOOL_DIR,chan->uniqueid);
|
||||||
duration = 5;
|
duration = 5;
|
||||||
|
|
||||||
if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_RECORDNAME))
|
if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_RECORDNAME))
|
||||||
if (ast_play_and_record(chan, "vm-rec-name", namerecloc, 5, "sln", &duration, 128, 0, NULL) < 0)
|
if (ast_play_and_record(chan, "vm-rec-name", namerecloc, 5, "sln", &duration, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE), 0, NULL) < 0)
|
||||||
goto outrun;
|
goto outrun;
|
||||||
|
|
||||||
if (!ast_fileexists(namerecloc, NULL, chan->language))
|
if (!ast_fileexists(namerecloc, NULL, chan->language))
|
||||||
ast_copy_string(namerecloc, "", sizeof(namerecloc));
|
ast_copy_string(namerecloc, "", sizeof(namerecloc));
|
||||||
|
|
||||||
if (ast_streamfile(chan, targs.plsholdprompt, chan->language))
|
if (ast_streamfile(chan, targs.plsholdprompt, chan->language))
|
||||||
goto outrun;
|
goto outrun;
|
||||||
if (ast_waitstream(chan, "") < 0)
|
if (ast_waitstream(chan, "") < 0)
|
||||||
goto outrun;
|
goto outrun;
|
||||||
ast_moh_start(chan, S_OR(targs.mohclass, NULL), NULL);
|
ast_moh_start(chan, S_OR(targs.mohclass, NULL), NULL);
|
||||||
|
|
||||||
targs.status = 0;
|
targs.status = 0;
|
||||||
targs.chan = chan;
|
targs.chan = chan;
|
||||||
ast_copy_string(targs.namerecloc, namerecloc, sizeof(targs.namerecloc));
|
ast_copy_string(targs.namerecloc, namerecloc, sizeof(targs.namerecloc));
|
||||||
|
|
||||||
findmeexec(&targs);
|
findmeexec(&targs);
|
||||||
|
|
||||||
while ((nm = AST_LIST_REMOVE_HEAD(&targs.cnumbers, entry)))
|
while ((nm = AST_LIST_REMOVE_HEAD(&targs.cnumbers, entry)))
|
||||||
ast_free(nm);
|
ast_free(nm);
|
||||||
|
|
||||||
if (!ast_strlen_zero(namerecloc))
|
if (!ast_strlen_zero(namerecloc))
|
||||||
unlink(namerecloc);
|
unlink(namerecloc);
|
||||||
|
|
||||||
if (targs.status != 100) {
|
if (targs.status != 100) {
|
||||||
ast_moh_stop(chan);
|
ast_moh_stop(chan);
|
||||||
if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_UNREACHABLEMSG))
|
if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_UNREACHABLEMSG))
|
||||||
|
@ -989,12 +981,12 @@ static int app_exec(struct ast_channel *chan, void *data)
|
||||||
caller = chan;
|
caller = chan;
|
||||||
outbound = targs.outbound;
|
outbound = targs.outbound;
|
||||||
/* Bridge the two channels. */
|
/* Bridge the two channels. */
|
||||||
|
|
||||||
memset(&config,0,sizeof(struct ast_bridge_config));
|
memset(&config, 0, sizeof(config));
|
||||||
ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
|
ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
|
||||||
ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
|
ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
|
||||||
ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
|
ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
|
||||||
|
|
||||||
ast_moh_stop(caller);
|
ast_moh_stop(caller);
|
||||||
/* Be sure no generators are left on it */
|
/* Be sure no generators are left on it */
|
||||||
ast_deactivate_generator(caller);
|
ast_deactivate_generator(caller);
|
||||||
|
@ -1006,7 +998,7 @@ static int app_exec(struct ast_channel *chan, void *data)
|
||||||
goto outrun;
|
goto outrun;
|
||||||
}
|
}
|
||||||
time(&answer_time);
|
time(&answer_time);
|
||||||
res = ast_bridge_call(caller,outbound,&config);
|
res = ast_bridge_call(caller, outbound, &config);
|
||||||
time(&end_time);
|
time(&end_time);
|
||||||
snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
|
snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
|
||||||
pbx_builtin_setvar_helper(caller, "DIALEDTIME", toast);
|
pbx_builtin_setvar_helper(caller, "DIALEDTIME", toast);
|
||||||
|
@ -1017,7 +1009,7 @@ static int app_exec(struct ast_channel *chan, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
outrun:
|
outrun:
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1051,7 +1043,7 @@ static int reload(void)
|
||||||
{
|
{
|
||||||
reload_followme(1);
|
reload_followme(1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Find-Me/Follow-Me Application",
|
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Find-Me/Follow-Me Application",
|
||||||
|
|
|
@ -1699,7 +1699,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
|
||||||
"%s/meetme/meetme-username-%s-%d", ast_config_AST_SPOOL_DIR,
|
"%s/meetme/meetme-username-%s-%d", ast_config_AST_SPOOL_DIR,
|
||||||
conf->confno, user->user_no);
|
conf->confno, user->user_no);
|
||||||
if (confflags & CONFFLAG_INTROUSERNOREVIEW)
|
if (confflags & CONFFLAG_INTROUSERNOREVIEW)
|
||||||
res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, 128, 0, NULL);
|
res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE), 0, NULL);
|
||||||
else
|
else
|
||||||
res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL);
|
res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL);
|
||||||
if (res == -1)
|
if (res == -1)
|
||||||
|
|
|
@ -2360,7 +2360,6 @@ static int load_config(int reload)
|
||||||
/* First, set some default settings */
|
/* First, set some default settings */
|
||||||
global_externnotify[0] = '\0';
|
global_externnotify[0] = '\0';
|
||||||
global_logfile[0] = '\0';
|
global_logfile[0] = '\0';
|
||||||
global_silencethreshold = 256;
|
|
||||||
global_vmmaxmessage = 2000;
|
global_vmmaxmessage = 2000;
|
||||||
global_maxgreet = 2000;
|
global_maxgreet = 2000;
|
||||||
global_vmminmessage = 0;
|
global_vmminmessage = 0;
|
||||||
|
@ -2375,6 +2374,8 @@ static int load_config(int reload)
|
||||||
memset(&global_stats, 0, sizeof(global_stats));
|
memset(&global_stats, 0, sizeof(global_stats));
|
||||||
global_stats.reset = ast_tvnow();
|
global_stats.reset = ast_tvnow();
|
||||||
|
|
||||||
|
global_silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
|
||||||
|
|
||||||
/* Make sure we could load configuration file */
|
/* Make sure we could load configuration file */
|
||||||
if (!cfg) {
|
if (!cfg) {
|
||||||
ast_log(LOG_WARNING, "Failed to load configuration file. Module activated with default settings.\n");
|
ast_log(LOG_WARNING, "Failed to load configuration file. Module activated with default settings.\n");
|
||||||
|
@ -2640,7 +2641,7 @@ static char *handle_minivm_show_settings(struct ast_cli_entry *e, int cmd, struc
|
||||||
ast_cli(a->fd, "\n");
|
ast_cli(a->fd, "\n");
|
||||||
ast_cli(a->fd, " Mail command (shell): %s\n", global_mailcmd);
|
ast_cli(a->fd, " Mail command (shell): %s\n", global_mailcmd);
|
||||||
ast_cli(a->fd, " Max silence: %d\n", global_maxsilence);
|
ast_cli(a->fd, " Max silence: %d\n", global_maxsilence);
|
||||||
ast_cli(a->fd, " Silence treshold: %d\n", global_silencethreshold);
|
ast_cli(a->fd, " Silence threshold: %d\n", global_silencethreshold);
|
||||||
ast_cli(a->fd, " Max message length (secs): %d\n", global_vmmaxmessage);
|
ast_cli(a->fd, " Max message length (secs): %d\n", global_vmmaxmessage);
|
||||||
ast_cli(a->fd, " Min message length (secs): %d\n", global_vmminmessage);
|
ast_cli(a->fd, " Min message length (secs): %d\n", global_vmminmessage);
|
||||||
ast_cli(a->fd, " Default format: %s\n", default_vmformat);
|
ast_cli(a->fd, " Default format: %s\n", default_vmformat);
|
||||||
|
|
|
@ -243,7 +243,7 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||||
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ast_dsp_set_threshold(sildet, 256);
|
ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the directory if it does not exist. */
|
/* Create the directory if it does not exist. */
|
||||||
|
|
|
@ -8399,7 +8399,7 @@ static int load_config(int reload)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Silence treshold */
|
/* Silence treshold */
|
||||||
silencethreshold = 256;
|
silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
|
||||||
if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
|
if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
|
||||||
silencethreshold = atoi(val);
|
silencethreshold = atoi(val);
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,12 @@
|
||||||
*
|
*
|
||||||
* \author David C. Troy <dave@popvox.com>
|
* \author David C. Troy <dave@popvox.com>
|
||||||
*
|
*
|
||||||
|
* \brief Wait For Noise
|
||||||
|
* The same as Wait For Silence but listenes noise on the chennel that is above \n
|
||||||
|
* the pre-configured silence threshold from dsp.conf
|
||||||
|
*
|
||||||
|
* \author Philipp Skadorov <skadorov@yahoo.com>
|
||||||
|
*
|
||||||
* \ingroup applications
|
* \ingroup applications
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -42,9 +48,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||||
#include "asterisk/dsp.h"
|
#include "asterisk/dsp.h"
|
||||||
#include "asterisk/module.h"
|
#include "asterisk/module.h"
|
||||||
|
|
||||||
static char *app = "WaitForSilence";
|
static char *app_silence = "WaitForSilence";
|
||||||
static char *synopsis = "Waits for a specified amount of silence";
|
static char *synopsis_silence = "Waits for a specified amount of silence";
|
||||||
static char *descrip =
|
static char *descrip_silence =
|
||||||
" WaitForSilence(silencerequired[,iterations][,timeout]):\n"
|
" WaitForSilence(silencerequired[,iterations][,timeout]):\n"
|
||||||
"Wait for Silence: Waits for up to 'silencerequired' \n"
|
"Wait for Silence: Waits for up to 'silencerequired' \n"
|
||||||
"milliseconds of silence, 'iterations' times or once if omitted.\n"
|
"milliseconds of silence, 'iterations' times or once if omitted.\n"
|
||||||
|
@ -68,15 +74,24 @@ static char *descrip =
|
||||||
"SILENCE - if exited with silence detected\n"
|
"SILENCE - if exited with silence detected\n"
|
||||||
"TIMEOUT - if exited without silence detected after timeout\n";
|
"TIMEOUT - if exited without silence detected after timeout\n";
|
||||||
|
|
||||||
static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstart, int timeout) {
|
static char *app_noise = "WaitForNoise";
|
||||||
|
static char *synopsis_noise = "Waits for a specified amount of noise";
|
||||||
|
static char *descrip_noise =
|
||||||
|
"WaitForNoise(noiserequired[,iterations][,timeout]) \n"
|
||||||
|
"Wait for Noise: The same as Wait for Silance but waits for noise that is above the threshold specified\n";
|
||||||
|
|
||||||
|
static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int timeout, int wait_for_silence) {
|
||||||
struct ast_frame *f;
|
struct ast_frame *f;
|
||||||
int dspsilence = 0;
|
int dsptime = 0;
|
||||||
static int silencethreshold = 128;
|
|
||||||
int rfmt = 0;
|
int rfmt = 0;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
struct ast_dsp *sildet; /* silence detector dsp */
|
struct ast_dsp *sildet; /* silence detector dsp */
|
||||||
time_t now;
|
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;
|
||||||
|
|
||||||
rfmt = chan->readformat; /* Set to linear mode */
|
rfmt = chan->readformat; /* Set to linear mode */
|
||||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
@ -89,15 +104,15 @@ static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstar
|
||||||
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ast_dsp_set_threshold(sildet, silencethreshold);
|
ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
|
||||||
|
|
||||||
/* Await silence... */
|
/* Await silence... */
|
||||||
f = NULL;
|
f = NULL;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
/* Start with no silence received */
|
/* Start with no silence received */
|
||||||
dspsilence = 0;
|
dsptime = 0;
|
||||||
|
|
||||||
res = ast_waitfor(chan, silencereqd);
|
res = ast_waitfor(chan, timereqd);
|
||||||
|
|
||||||
/* Must have gotten a hangup; let's exit */
|
/* Must have gotten a hangup; let's exit */
|
||||||
if (res <= 0) {
|
if (res <= 0) {
|
||||||
|
@ -107,30 +122,36 @@ static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstar
|
||||||
|
|
||||||
/* We waited and got no frame; sounds like digital silence or a muted digital channel */
|
/* We waited and got no frame; sounds like digital silence or a muted digital channel */
|
||||||
if (!res) {
|
if (!res) {
|
||||||
dspsilence = silencereqd;
|
dsptime = timereqd;
|
||||||
} else {
|
} else {
|
||||||
/* Looks like we did get a frame, so let's check it out */
|
/* Looks like we did get a frame, so let's check it out */
|
||||||
f = ast_read(chan);
|
f = ast_read(chan);
|
||||||
if (!f)
|
if (!f)
|
||||||
break;
|
break;
|
||||||
if (f && f->frametype == AST_FRAME_VOICE) {
|
if (f && f->frametype == AST_FRAME_VOICE) {
|
||||||
ast_dsp_silence(sildet, f, &dspsilence);
|
ast_dsp_func(sildet, f, &dsptime);
|
||||||
ast_frfree(f);
|
ast_frfree(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_verb(3, "Got %dms silence< %dms required\n", dspsilence, silencereqd);
|
if (wait_for_silence)
|
||||||
|
ast_verb(6, "Got %dms silence < %dms required\n", dsptime, timereqd);
|
||||||
|
else
|
||||||
|
ast_verb(6, "Got %dms noise < %dms required\n", dsptime, timereqd);
|
||||||
|
|
||||||
if (dspsilence >= silencereqd) {
|
if (dsptime >= timereqd) {
|
||||||
ast_verb(3, "Exiting with %dms silence >= %dms required\n", dspsilence, silencereqd);
|
if (wait_for_silence)
|
||||||
|
ast_verb(3, "Exiting with %dms silence >= %dms required\n", dsptime, timereqd);
|
||||||
|
else
|
||||||
|
ast_verb(3, "Exiting with %dms noise >= %dms required\n", dsptime, timereqd);
|
||||||
/* Ended happily with silence */
|
/* Ended happily with silence */
|
||||||
res = 1;
|
res = 1;
|
||||||
pbx_builtin_setvar_helper(chan, "WAITSTATUS", "SILENCE");
|
pbx_builtin_setvar_helper(chan, "WAITSTATUS", wait_for_silence ? "SILENCE" : "NOISE");
|
||||||
ast_debug(1, "WAITSTATUS was set to SILENCE\n");
|
ast_debug(1, "WAITSTATUS was set to %s\n", wait_for_silence ? "SILENCE" : "NOISE");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( timeout && (difftime(time(&now),waitstart) >= timeout) ) {
|
if (timeout && (difftime(time(&now), waitstart) >= timeout)) {
|
||||||
pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
|
pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
|
||||||
ast_debug(1, "WAITSTATUS was set to TIMEOUT\n");
|
ast_debug(1, "WAITSTATUS was set to TIMEOUT\n");
|
||||||
res = 0;
|
res = 0;
|
||||||
|
@ -146,43 +167,60 @@ static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstar
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int waitforsilence_exec(struct ast_channel *chan, void *data)
|
static int waitfor_exec(struct ast_channel *chan, void *data, int wait_for_silence)
|
||||||
{
|
{
|
||||||
int res = 1;
|
int res = 1;
|
||||||
int silencereqd = 1000;
|
int timereqd = 1000;
|
||||||
int timeout = 0;
|
int timeout = 0;
|
||||||
int iterations = 1, i;
|
int iterations = 1, i;
|
||||||
time_t waitstart;
|
time_t waitstart;
|
||||||
|
|
||||||
res = ast_answer(chan); /* Answer the channel */
|
res = ast_answer(chan); /* Answer the channel */
|
||||||
|
|
||||||
if (!data || ( (sscanf(data, "%d,%d,%d", &silencereqd, &iterations, &timeout) != 3) &&
|
if (!data || ( (sscanf(data, "%d,%d,%d", &timereqd, &iterations, &timeout) != 3) &&
|
||||||
(sscanf(data, "%d|%d", &silencereqd, &iterations) != 2) &&
|
(sscanf(data, "%d,%d", &timereqd, &iterations) != 2) &&
|
||||||
(sscanf(data, "%d", &silencereqd) != 1) ) ) {
|
(sscanf(data, "%d", &timereqd) != 1) ) ) {
|
||||||
ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration, no timeout\n");
|
ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration, no timeout\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_verb(3, "Waiting %d time(s) for %d ms silence with %d timeout\n", iterations, silencereqd, timeout);
|
ast_verb(3, "Waiting %d time(s) for %d ms silence with %d timeout\n", iterations, timereqd, timeout);
|
||||||
|
|
||||||
time(&waitstart);
|
time(&waitstart);
|
||||||
res = 1;
|
res = 1;
|
||||||
for (i=0; (i<iterations) && (res == 1); i++) {
|
for (i=0; (i<iterations) && (res == 1); i++) {
|
||||||
res = do_waiting(chan, silencereqd, waitstart, timeout);
|
res = do_waiting(chan, timereqd, waitstart, timeout, wait_for_silence);
|
||||||
}
|
}
|
||||||
if (res > 0)
|
if (res > 0)
|
||||||
res = 0;
|
res = 0;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int waitforsilence_exec(struct ast_channel *chan, void *data)
|
||||||
|
{
|
||||||
|
return waitfor_exec(chan, data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int waitfornoise_exec(struct ast_channel *chan, void *data)
|
||||||
|
{
|
||||||
|
return waitfor_exec(chan, data, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static int unload_module(void)
|
static int unload_module(void)
|
||||||
{
|
{
|
||||||
return ast_unregister_application(app);
|
int res;
|
||||||
|
res = ast_unregister_application(app_silence);
|
||||||
|
res |= ast_unregister_application(app_noise);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_module(void)
|
static int load_module(void)
|
||||||
{
|
{
|
||||||
return ast_register_application(app, waitforsilence_exec, synopsis, descrip);
|
int res;
|
||||||
|
|
||||||
|
res = ast_register_application(app_silence, waitforsilence_exec, synopsis_silence, descrip_silence);
|
||||||
|
res |= ast_register_application(app_noise, waitfornoise_exec, synopsis_noise, descrip_noise);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Wait For Silence");
|
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Wait For Silence");
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[default]
|
||||||
|
;
|
||||||
|
; Length of sound (in milliseconds) before a period of silence is considered
|
||||||
|
; to be a change from talking to silence or a period of noise converts silence
|
||||||
|
; to talking. [default=256]
|
||||||
|
;
|
||||||
|
;silencethreshold=256
|
|
@ -58,6 +58,13 @@
|
||||||
|
|
||||||
struct ast_dsp;
|
struct ast_dsp;
|
||||||
|
|
||||||
|
enum threshold {
|
||||||
|
/* Array offsets */
|
||||||
|
THRESHOLD_SILENCE = 0,
|
||||||
|
/* Always the last */
|
||||||
|
THRESHOLD_MAX = 1,
|
||||||
|
};
|
||||||
|
|
||||||
struct ast_dsp *ast_dsp_new(void);
|
struct ast_dsp *ast_dsp_new(void);
|
||||||
void ast_dsp_free(struct ast_dsp *dsp);
|
void ast_dsp_free(struct ast_dsp *dsp);
|
||||||
|
|
||||||
|
@ -84,6 +91,10 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
|
||||||
number of seconds of silence */
|
number of seconds of silence */
|
||||||
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence);
|
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence);
|
||||||
|
|
||||||
|
/*! \brief Return non-zero if this is noise. Updates "totalnoise" with the total
|
||||||
|
number of seconds of noise */
|
||||||
|
int ast_dsp_noise(struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise);
|
||||||
|
|
||||||
/*! \brief Return non-zero if historically this should be a busy, request that
|
/*! \brief Return non-zero if historically this should be a busy, request that
|
||||||
ast_dsp_silence has already been called */
|
ast_dsp_silence has already been called */
|
||||||
int ast_dsp_busydetect(struct ast_dsp *dsp);
|
int ast_dsp_busydetect(struct ast_dsp *dsp);
|
||||||
|
@ -115,4 +126,12 @@ int ast_dsp_get_tstate(struct ast_dsp *dsp);
|
||||||
/*! \brief Get tcount (Threshold counter) */
|
/*! \brief Get tcount (Threshold counter) */
|
||||||
int ast_dsp_get_tcount(struct ast_dsp *dsp);
|
int ast_dsp_get_tcount(struct ast_dsp *dsp);
|
||||||
|
|
||||||
|
/*! \brief Get silence threshold from dsp.conf*/
|
||||||
|
int ast_dsp_get_threshold_from_settings(enum threshold which);
|
||||||
|
|
||||||
|
/* \brief Reloads dsp settings from dsp.conf*/
|
||||||
|
int ast_dsp_reload(void);
|
||||||
|
|
||||||
|
int ast_dsp_init(void);
|
||||||
|
|
||||||
#endif /* _ASTERISK_DSP_H */
|
#endif /* _ASTERISK_DSP_H */
|
||||||
|
|
|
@ -1268,7 +1268,7 @@ int ast_unlock_path(const char *path)
|
||||||
|
|
||||||
int ast_record_review(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path)
|
int ast_record_review(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path)
|
||||||
{
|
{
|
||||||
int silencethreshold = 128;
|
int silencethreshold;
|
||||||
int maxsilence = 0;
|
int maxsilence = 0;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
int cmd = 0;
|
int cmd = 0;
|
||||||
|
@ -1286,6 +1286,8 @@ int ast_record_review(struct ast_channel *chan, const char *playfile, const char
|
||||||
|
|
||||||
cmd = '3'; /* Want to start by recording */
|
cmd = '3'; /* Want to start by recording */
|
||||||
|
|
||||||
|
silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
|
||||||
|
|
||||||
while ((cmd >= 0) && (cmd != 't')) {
|
while ((cmd >= 0) && (cmd != 't')) {
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case '1':
|
case '1':
|
||||||
|
|
|
@ -121,6 +121,7 @@ int daemon(int, int); /* defined in libresolv of all places */
|
||||||
#include "asterisk/linkedlists.h"
|
#include "asterisk/linkedlists.h"
|
||||||
#include "asterisk/devicestate.h"
|
#include "asterisk/devicestate.h"
|
||||||
#include "asterisk/module.h"
|
#include "asterisk/module.h"
|
||||||
|
#include "asterisk/dsp.h"
|
||||||
|
|
||||||
#include "asterisk/doxyref.h" /* Doxygen documentation */
|
#include "asterisk/doxyref.h" /* Doxygen documentation */
|
||||||
|
|
||||||
|
@ -3218,7 +3219,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_rtp_init();
|
ast_rtp_init();
|
||||||
|
ast_dsp_init();
|
||||||
ast_udptl_init();
|
ast_udptl_init();
|
||||||
|
|
||||||
if (ast_image_init()) {
|
if (ast_image_init()) {
|
||||||
|
|
71
main/dsp.c
71
main/dsp.c
|
@ -53,6 +53,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||||
#include "asterisk/alaw.h"
|
#include "asterisk/alaw.h"
|
||||||
#include "asterisk/utils.h"
|
#include "asterisk/utils.h"
|
||||||
#include "asterisk/options.h"
|
#include "asterisk/options.h"
|
||||||
|
#include "asterisk/config.h"
|
||||||
|
|
||||||
/*! Number of goertzels for progress detect */
|
/*! Number of goertzels for progress detect */
|
||||||
enum gsamp_size {
|
enum gsamp_size {
|
||||||
|
@ -193,6 +194,8 @@ enum gsamp_thresh {
|
||||||
#define SAMPLES_IN_FRAME 160
|
#define SAMPLES_IN_FRAME 160
|
||||||
|
|
||||||
|
|
||||||
|
#define CONFIG_FILE_NAME "dsp.conf"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int v2;
|
int v2;
|
||||||
int v3;
|
int v3;
|
||||||
|
@ -272,6 +275,8 @@ static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
|
||||||
|
|
||||||
static char bell_mf_positions[] = "1247C-358A--69*---0B----#";
|
static char bell_mf_positions[] = "1247C-358A--69*---0B----#";
|
||||||
|
|
||||||
|
static int thresholds[THRESHOLD_MAX];
|
||||||
|
|
||||||
static inline void goertzel_sample(goertzel_state_t *s, short sample)
|
static inline void goertzel_sample(goertzel_state_t *s, short sample)
|
||||||
{
|
{
|
||||||
int v1;
|
int v1;
|
||||||
|
@ -1021,7 +1026,7 @@ int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
|
||||||
return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
|
return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totalsilence)
|
static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise)
|
||||||
{
|
{
|
||||||
int accum;
|
int accum;
|
||||||
int x;
|
int x;
|
||||||
|
@ -1073,6 +1078,8 @@ static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totals
|
||||||
}
|
}
|
||||||
if (totalsilence)
|
if (totalsilence)
|
||||||
*totalsilence = dsp->totalsilence;
|
*totalsilence = dsp->totalsilence;
|
||||||
|
if (totalnoise)
|
||||||
|
*totalnoise = dsp->totalnoise;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1179,9 +1186,28 @@ int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
|
||||||
}
|
}
|
||||||
s = f->data;
|
s = f->data;
|
||||||
len = f->datalen/2;
|
len = f->datalen/2;
|
||||||
return __ast_dsp_silence(dsp, s, len, totalsilence);
|
return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ast_dsp_noise(struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
|
||||||
|
{
|
||||||
|
short *s;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (f->frametype != AST_FRAME_VOICE) {
|
||||||
|
ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (f->subclass != AST_FORMAT_SLINEAR) {
|
||||||
|
ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
s = f->data;
|
||||||
|
len = f->datalen/2;
|
||||||
|
return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
|
struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
|
||||||
{
|
{
|
||||||
int silence;
|
int silence;
|
||||||
|
@ -1236,7 +1262,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
|
||||||
ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
|
ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
|
||||||
return af;
|
return af;
|
||||||
}
|
}
|
||||||
silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
|
res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL);
|
||||||
if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
|
if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
|
||||||
memset(&dsp->f, 0, sizeof(dsp->f));
|
memset(&dsp->f, 0, sizeof(dsp->f));
|
||||||
dsp->f.frametype = AST_FRAME_NULL;
|
dsp->f.frametype = AST_FRAME_NULL;
|
||||||
|
@ -1516,3 +1542,42 @@ int ast_dsp_get_tcount(struct ast_dsp *dsp)
|
||||||
{
|
{
|
||||||
return dsp->tcount;
|
return dsp->tcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _dsp_init(int reload)
|
||||||
|
{
|
||||||
|
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
|
||||||
|
struct ast_config *cfg;
|
||||||
|
struct ast_variable *var;
|
||||||
|
|
||||||
|
cfg = ast_config_load(CONFIG_FILE_NAME, config_flags);
|
||||||
|
|
||||||
|
if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED) {
|
||||||
|
const char *value;
|
||||||
|
|
||||||
|
value = ast_variable_retrieve(cfg, "default", "silencethreshold");
|
||||||
|
if (value && sscanf(value, "%d", &thresholds[THRESHOLD_SILENCE]) != 1) {
|
||||||
|
ast_log(LOG_WARNING, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, var->value);
|
||||||
|
thresholds[THRESHOLD_SILENCE] = 256;
|
||||||
|
} else if (!value)
|
||||||
|
thresholds[THRESHOLD_SILENCE] = 256;
|
||||||
|
|
||||||
|
ast_config_destroy(cfg);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ast_dsp_get_threshold_from_settings(enum threshold which)
|
||||||
|
{
|
||||||
|
return thresholds[which];
|
||||||
|
}
|
||||||
|
|
||||||
|
int ast_dsp_init(void)
|
||||||
|
{
|
||||||
|
return _dsp_init(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ast_dsp_reload(void)
|
||||||
|
{
|
||||||
|
return _dsp_init(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||||
#include "asterisk/http.h"
|
#include "asterisk/http.h"
|
||||||
#include "asterisk/lock.h"
|
#include "asterisk/lock.h"
|
||||||
#include "asterisk/features.h"
|
#include "asterisk/features.h"
|
||||||
|
#include "asterisk/dsp.h"
|
||||||
|
|
||||||
#ifdef DLFCNCOMPAT
|
#ifdef DLFCNCOMPAT
|
||||||
#include "asterisk/dlfcn-compat.h"
|
#include "asterisk/dlfcn-compat.h"
|
||||||
|
@ -249,6 +250,7 @@ static struct reload_classes {
|
||||||
{ "http", ast_http_reload },
|
{ "http", ast_http_reload },
|
||||||
{ "logger", logger_reload },
|
{ "logger", logger_reload },
|
||||||
{ "features", ast_features_reload },
|
{ "features", ast_features_reload },
|
||||||
|
{ "dsp", ast_dsp_reload},
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1296,7 +1296,7 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
|
||||||
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ast_dsp_set_threshold(sildet, 256);
|
ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* backward compatibility, if no offset given, arg[6] would have been
|
/* backward compatibility, if no offset given, arg[6] would have been
|
||||||
|
|
Reference in New Issue