mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-27 12:56:15 +00:00
Merge branch 'master' of ssh://git.freeswitch.org:222/freeswitch
This commit is contained in:
commit
f4098ebba6
12
conf/autoload_configs/cepstral.conf.xml
Normal file
12
conf/autoload_configs/cepstral.conf.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<configuration name="cepstral.conf" description="Cepstral TTS configuration">
|
||||||
|
<settings>
|
||||||
|
<!--
|
||||||
|
Possible encodings:
|
||||||
|
* utf-8
|
||||||
|
* us-ascii
|
||||||
|
* iso8859-1 (default)
|
||||||
|
* iso8859-15
|
||||||
|
-->
|
||||||
|
<param name="encoding" value="utf-8"/>
|
||||||
|
</settings>
|
||||||
|
</configuration>
|
11
conf/lang/en/ivr/sounds.xml
Normal file
11
conf/lang/en/ivr/sounds.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<include> <!--This line will be ignored it's here to validate the xml and is optional -->
|
||||||
|
<macro name="queue_position">
|
||||||
|
<input pattern="^(\d+)$">
|
||||||
|
<match>
|
||||||
|
<action function="play-file" data="ivr/ivr-you_are_number.wav"/>
|
||||||
|
<action function="say" data="$1" method="pronounced" type="items"/>
|
||||||
|
<action function="play-file" data="ivr/ivr-in_line.wav"/>
|
||||||
|
</match>
|
||||||
|
</input>
|
||||||
|
</macro>
|
||||||
|
</include>
|
@ -437,7 +437,10 @@
|
|||||||
<prompt phrase="Recording started." filename="ivr-recording_started.wav"/>
|
<prompt phrase="Recording started." filename="ivr-recording_started.wav"/>
|
||||||
<prompt phrase="Recording stopped." filename="ivr-recording_stopped.wav"/>
|
<prompt phrase="Recording stopped." filename="ivr-recording_stopped.wav"/>
|
||||||
<prompt phrase="Recording deleted." filename="ivr-recording_deleted.wav"/>
|
<prompt phrase="Recording deleted." filename="ivr-recording_deleted.wav"/>
|
||||||
|
<prompt phrase="You are no longer in line." filename="ivr-no_longer_in_line.wav"/>
|
||||||
|
<prompt phrase="question..." filename="ivr-question.wav"/>
|
||||||
|
<prompt phrase="...has been answered." filename="ivr-has_been_answered.wav"/>
|
||||||
|
<prompt phrase="...has been removed." filename="ivr=has_been_removed.wav"/>
|
||||||
</ivr>
|
</ivr>
|
||||||
<misc>
|
<misc>
|
||||||
<prompt phrase="This call has been secured" filename="call_secured.wav"/>
|
<prompt phrase="This call has been secured" filename="call_secured.wav"/>
|
||||||
|
@ -1772,9 +1772,10 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
|
|||||||
const char *agent_wrap_up_time = argv[11];
|
const char *agent_wrap_up_time = argv[11];
|
||||||
const char *agent_state = argv[12];
|
const char *agent_state = argv[12];
|
||||||
const char *agent_ready_time = argv[13];
|
const char *agent_ready_time = argv[13];
|
||||||
const char *agent_tier_level = argv[14];
|
const char *agent_tier_position = argv[14];
|
||||||
const char *agent_type = argv[15];
|
const char *agent_tier_level = argv[15];
|
||||||
const char *agent_uuid = argv[16];
|
const char *agent_type = argv[16];
|
||||||
|
const char *agent_uuid = argv[17];
|
||||||
|
|
||||||
switch_bool_t contact_agent = SWITCH_TRUE;
|
switch_bool_t contact_agent = SWITCH_TRUE;
|
||||||
|
|
||||||
@ -1887,7 +1888,15 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
|
|||||||
h->busy_delay_time = atoi(agent_busy_delay_time);
|
h->busy_delay_time = atoi(agent_busy_delay_time);
|
||||||
h->no_answer_delay_time = atoi(agent_no_answer_delay_time);
|
h->no_answer_delay_time = atoi(agent_no_answer_delay_time);
|
||||||
|
|
||||||
|
if (!strcasecmp(cbt->strategy, "top-down")) {
|
||||||
|
switch_core_session_t *member_session = switch_core_session_locate(cbt->member_session_uuid);
|
||||||
|
if (member_session) {
|
||||||
|
switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
|
||||||
|
switch_channel_set_variable(member_channel, "cc_last_agent_tier_position", agent_tier_position);
|
||||||
|
switch_channel_set_variable(member_channel, "cc_last_agent_tier_level", agent_tier_level);
|
||||||
|
switch_core_session_rwunlock(member_session);
|
||||||
|
}
|
||||||
|
}
|
||||||
cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_RECEIVING), h->agent_name);
|
cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_RECEIVING), h->agent_name);
|
||||||
|
|
||||||
sql = switch_mprintf(
|
sql = switch_mprintf(
|
||||||
@ -1995,6 +2004,61 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
|
|||||||
cbt.record_template = queue_record_template;
|
cbt.record_template = queue_record_template;
|
||||||
cbt.agent_found = SWITCH_FALSE;
|
cbt.agent_found = SWITCH_FALSE;
|
||||||
|
|
||||||
|
if (!strcasecmp(queue->strategy, "top-down")) {
|
||||||
|
/* WARNING this use channel variable to help dispatch... might need to be reviewed to save it in DB to make this multi server prooft in the future */
|
||||||
|
switch_core_session_t *member_session = switch_core_session_locate(cbt.member_session_uuid);
|
||||||
|
int position = 0, level = 0;
|
||||||
|
const char *last_agent_tier_position, *last_agent_tier_level;
|
||||||
|
if (member_session) {
|
||||||
|
switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
|
||||||
|
|
||||||
|
if ((last_agent_tier_position = switch_channel_get_variable(member_channel, "cc_last_agent_tier_position"))) {
|
||||||
|
position = atoi(last_agent_tier_position);
|
||||||
|
}
|
||||||
|
if ((last_agent_tier_level = switch_channel_get_variable(member_channel, "cc_last_agent_tier_level"))) {
|
||||||
|
level = atoi(last_agent_tier_level);
|
||||||
|
}
|
||||||
|
switch_core_session_rwunlock(member_session);
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = switch_mprintf("SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position as tiers_position, tiers.level as tiers_level, agents.type, agents.uuid, agents.last_offered_call as agents_last_offered_call, 1 as dyn_order FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)"
|
||||||
|
" WHERE tiers.queue = '%q'"
|
||||||
|
" AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')"
|
||||||
|
" AND tiers.position > %d"
|
||||||
|
" AND tiers.level = %d"
|
||||||
|
" UNION "
|
||||||
|
"SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position as tiers_position, tiers.level as tiers_level, agents.type, agents.uuid, agents.last_offered_call as agents_last_offered_call, 2 as dyn_order FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)"
|
||||||
|
" WHERE tiers.queue = '%q'"
|
||||||
|
" AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')"
|
||||||
|
" ORDER BY dyn_order asc, tiers_level, tiers_position, agents_last_offered_call",
|
||||||
|
queue_name,
|
||||||
|
cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE), cc_agent_status2str(CC_AGENT_STATUS_ON_BREAK), cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE_ON_DEMAND),
|
||||||
|
position,
|
||||||
|
level,
|
||||||
|
queue_name,
|
||||||
|
cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE), cc_agent_status2str(CC_AGENT_STATUS_ON_BREAK), cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE_ON_DEMAND)
|
||||||
|
);
|
||||||
|
} else if (!strcasecmp(queue->strategy, "round-robin")) {
|
||||||
|
sql = switch_mprintf("SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position as tiers_position, tiers.level as tiers_level, agents.type, agents.uuid, agents.last_offered_call as agents_last_offered_call, 1 as dyn_order FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)"
|
||||||
|
" WHERE tiers.queue = '%q'"
|
||||||
|
" AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')"
|
||||||
|
" AND tiers.position > (SELECT tiers.position FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent) WHERE tiers.queue = '%q' AND agents.last_offered_call > 0 ORDER BY agents.last_offered_call DESC LIMIT 1)"
|
||||||
|
" AND tiers.level = (SELECT tiers.level FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent) WHERE tiers.queue = '%q' AND agents.last_offered_call > 0 ORDER BY agents.last_offered_call DESC LIMIT 1)"
|
||||||
|
" UNION "
|
||||||
|
"SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position as tiers_position, tiers.level as tiers_level, agents.type, agents.uuid, agents.last_offered_call as agents_last_offered_call, 2 as dyn_order FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)"
|
||||||
|
" WHERE tiers.queue = '%q'"
|
||||||
|
" AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')"
|
||||||
|
" ORDER BY dyn_order asc, tiers_level, tiers_position, agents_last_offered_call",
|
||||||
|
queue_name,
|
||||||
|
cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE), cc_agent_status2str(CC_AGENT_STATUS_ON_BREAK), cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE_ON_DEMAND),
|
||||||
|
queue_name,
|
||||||
|
queue_name,
|
||||||
|
queue_name,
|
||||||
|
cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE), cc_agent_status2str(CC_AGENT_STATUS_ON_BREAK), cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE_ON_DEMAND)
|
||||||
|
);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
if (!strcasecmp(queue->strategy, "longest-idle-agent")) {
|
if (!strcasecmp(queue->strategy, "longest-idle-agent")) {
|
||||||
sql_order_by = switch_mprintf("level, agents.last_offered_call, position");
|
sql_order_by = switch_mprintf("level, agents.last_offered_call, position");
|
||||||
} else if (!strcasecmp(queue_strategy, "agent-with-least-talk-time")) {
|
} else if (!strcasecmp(queue_strategy, "agent-with-least-talk-time")) {
|
||||||
@ -2007,6 +2071,8 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
|
|||||||
cc_execute_sql(NULL, sql, NULL);
|
cc_execute_sql(NULL, sql, NULL);
|
||||||
switch_safe_free(sql);
|
switch_safe_free(sql);
|
||||||
sql_order_by = switch_mprintf("level, position");
|
sql_order_by = switch_mprintf("level, position");
|
||||||
|
} else if(!strcasecmp(queue_strategy, "random")) {
|
||||||
|
sql_order_by = switch_mprintf("level, random()");
|
||||||
} else if(!strcasecmp(queue_strategy, "sequentially-by-agent-order")) {
|
} else if(!strcasecmp(queue_strategy, "sequentially-by-agent-order")) {
|
||||||
sql_order_by = switch_mprintf("level, position, agents.last_offered_call"); /* Default to last_offered_call, let add new strategy if needing it differently */
|
sql_order_by = switch_mprintf("level, position, agents.last_offered_call"); /* Default to last_offered_call, let add new strategy if needing it differently */
|
||||||
} else {
|
} else {
|
||||||
@ -2014,18 +2080,20 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
|
|||||||
sql_order_by = switch_mprintf("level, position, agents.last_offered_call");
|
sql_order_by = switch_mprintf("level, position, agents.last_offered_call");
|
||||||
}
|
}
|
||||||
|
|
||||||
sql = switch_mprintf("SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.level, agents.type, agents.uuid FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)"
|
sql = switch_mprintf("SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position, tiers.level, agents.type, agents.uuid FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)"
|
||||||
" WHERE tiers.queue = '%q'"
|
" WHERE tiers.queue = '%q'"
|
||||||
" AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')"
|
" AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')"
|
||||||
" ORDER BY %q",
|
" ORDER BY %q",
|
||||||
queue_name,
|
queue_name,
|
||||||
cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE), cc_agent_status2str(CC_AGENT_STATUS_ON_BREAK), cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE_ON_DEMAND),
|
cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE), cc_agent_status2str(CC_AGENT_STATUS_ON_BREAK), cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE_ON_DEMAND),
|
||||||
sql_order_by);
|
sql_order_by);
|
||||||
|
switch_safe_free(sql_order_by);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, agents_callback, &cbt /* Call back variables */);
|
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, agents_callback, &cbt /* Call back variables */);
|
||||||
|
|
||||||
switch_safe_free(sql);
|
switch_safe_free(sql);
|
||||||
switch_safe_free(sql_order_by);
|
|
||||||
|
|
||||||
/* We update a field in the queue struct so we can kick caller out if waiting for too long with no agent */
|
/* We update a field in the queue struct so we can kick caller out if waiting for too long with no agent */
|
||||||
if (!cbt.queue_name || !(queue = get_queue(cbt.queue_name))) {
|
if (!cbt.queue_name || !(queue = get_queue(cbt.queue_name))) {
|
||||||
@ -2360,7 +2428,7 @@ SWITCH_STANDARD_APP(callcenter_function)
|
|||||||
switch_safe_free(sql);
|
switch_safe_free(sql);
|
||||||
|
|
||||||
/* Confirm we took that member in */
|
/* Confirm we took that member in */
|
||||||
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q' AND session_uuid = '%q' AND state = '%q' AND queue = '%q'", member_session, member_session_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), queue_name);
|
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q' AND session_uuid = '%q' AND state = '%q' AND queue = '%q'", member_uuid, member_session_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), queue_name);
|
||||||
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
|
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
|
||||||
switch_safe_free(sql);
|
switch_safe_free(sql);
|
||||||
|
|
||||||
|
@ -531,17 +531,34 @@ SWITCH_STANDARD_API(hash_api_function)
|
|||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HASH_DUMP_SYNTAX "all|limit|db"
|
#define HASH_DUMP_SYNTAX "all|limit|db [<realm>]"
|
||||||
SWITCH_STANDARD_API(hash_dump_function)
|
SWITCH_STANDARD_API(hash_dump_function)
|
||||||
{
|
{
|
||||||
int mode;
|
int mode;
|
||||||
switch_hash_index_t *hi;
|
switch_hash_index_t *hi;
|
||||||
|
int argc = 0;
|
||||||
|
char *argv[4] = { 0 };
|
||||||
|
char *mydata = NULL;
|
||||||
|
int realm = 0;
|
||||||
|
char *realmvalue = NULL;
|
||||||
|
|
||||||
if (zstr(cmd)) {
|
if (!zstr(cmd)) {
|
||||||
|
mydata = strdup(cmd);
|
||||||
|
switch_assert(mydata);
|
||||||
|
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||||
|
} else {
|
||||||
|
realmvalue = "test";
|
||||||
|
realm = 0;
|
||||||
stream->write_function(stream, "Usage: "HASH_DUMP_SYNTAX"\n");
|
stream->write_function(stream, "Usage: "HASH_DUMP_SYNTAX"\n");
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd = strdup(argv[0]);
|
||||||
|
if (argc == 2) {
|
||||||
|
realm = 1;
|
||||||
|
realmvalue = switch_mprintf("%s_", argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(cmd, "all")) {
|
if (!strcmp(cmd, "all")) {
|
||||||
mode = 3;
|
mode = 3;
|
||||||
} else if (!strcmp(cmd, "limit")) {
|
} else if (!strcmp(cmd, "limit")) {
|
||||||
@ -553,7 +570,6 @@ SWITCH_STANDARD_API(hash_dump_function)
|
|||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (mode & 1) {
|
if (mode & 1) {
|
||||||
switch_thread_rwlock_rdlock(globals.limit_hash_rwlock);
|
switch_thread_rwlock_rdlock(globals.limit_hash_rwlock);
|
||||||
for (hi = switch_hash_first(NULL, globals.limit_hash); hi; hi = switch_hash_next(hi)) {
|
for (hi = switch_hash_first(NULL, globals.limit_hash); hi; hi = switch_hash_next(hi)) {
|
||||||
@ -577,9 +593,14 @@ SWITCH_STANDARD_API(hash_dump_function)
|
|||||||
const void *key;
|
const void *key;
|
||||||
switch_ssize_t keylen;
|
switch_ssize_t keylen;
|
||||||
switch_hash_this(hi, &key, &keylen, &val);
|
switch_hash_this(hi, &key, &keylen, &val);
|
||||||
|
if (realm) {
|
||||||
|
if (strstr(key, realmvalue)) {
|
||||||
stream->write_function(stream, "D/%s/%s\n", key, (char*)val);
|
stream->write_function(stream, "D/%s/%s\n", key, (char*)val);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
stream->write_function(stream, "D/%s/%s\n", key, (char*)val);
|
||||||
|
}
|
||||||
|
}
|
||||||
switch_thread_rwlock_unlock(globals.db_hash_rwlock);
|
switch_thread_rwlock_unlock(globals.db_hash_rwlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ struct callback_obj {
|
|||||||
profile_t *profile;
|
profile_t *profile;
|
||||||
switch_core_session_t *session;
|
switch_core_session_t *session;
|
||||||
switch_event_t *event;
|
switch_event_t *event;
|
||||||
float sell_rate;
|
float max_rate;
|
||||||
};
|
};
|
||||||
typedef struct callback_obj callback_t;
|
typedef struct callback_obj callback_t;
|
||||||
|
|
||||||
@ -622,6 +622,9 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
|
|||||||
} else if (CF("lcr_carrier_name")) {
|
} else if (CF("lcr_carrier_name")) {
|
||||||
additional->carrier_name = switch_core_strdup(pool, switch_str_nil(argv[i]));
|
additional->carrier_name = switch_core_strdup(pool, switch_str_nil(argv[i]));
|
||||||
} else if (CF("lcr_rate_field")) {
|
} else if (CF("lcr_rate_field")) {
|
||||||
|
if (!argv[i] || zstr(argv[i])) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
additional->rate = (float)atof(switch_str_nil(argv[i]));
|
additional->rate = (float)atof(switch_str_nil(argv[i]));
|
||||||
additional->rate_str = switch_core_sprintf(pool, "%0.5f", additional->rate);
|
additional->rate_str = switch_core_sprintf(pool, "%0.5f", additional->rate);
|
||||||
} else if (CF("lcr_gw_prefix")) {
|
} else if (CF("lcr_gw_prefix")) {
|
||||||
@ -669,8 +672,10 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
|
|||||||
|
|
||||||
|
|
||||||
for (current = cbt->head; current; current = current->next) {
|
for (current = cbt->head; current; current = current->next) {
|
||||||
if (cbt->sell_rate && cbt->sell_rate > current->rate) {
|
if (cbt->max_rate && (cbt->max_rate < additional->rate)) {
|
||||||
continue;
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Skipping [%s] because [%f] is higher than the max_rate of [%f]\n",
|
||||||
|
additional->carrier_name, additional->rate, cbt->max_rate);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = switch_core_sprintf(pool, "%s:%s", additional->gw_prefix, additional->gw_suffix);
|
key = switch_core_sprintf(pool, "%s:%s", additional->gw_prefix, additional->gw_suffix);
|
||||||
@ -852,9 +857,9 @@ static switch_status_t lcr_do_lookup(callback_t *cb_struct)
|
|||||||
if (cb_struct->session) {
|
if (cb_struct->session) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(cb_struct->session), SWITCH_LOG_DEBUG, "we have a session\n");
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(cb_struct->session), SWITCH_LOG_DEBUG, "we have a session\n");
|
||||||
if ((channel = switch_core_session_get_channel(cb_struct->session))) {
|
if ((channel = switch_core_session_get_channel(cb_struct->session))) {
|
||||||
const char *sell_rate = switch_channel_get_variable(channel, "sell_rate");
|
const char *max_rate = switch_channel_get_variable(channel, "max_rate");
|
||||||
if (!zstr(sell_rate)) {
|
if (!zstr(max_rate)) {
|
||||||
cb_struct->sell_rate = atof(sell_rate);
|
cb_struct->max_rate = atof(max_rate);
|
||||||
}
|
}
|
||||||
switch_channel_set_variable_var_check(channel, "lcr_rate_field", rate_field, SWITCH_FALSE);
|
switch_channel_set_variable_var_check(channel, "lcr_rate_field", rate_field, SWITCH_FALSE);
|
||||||
switch_channel_set_variable_var_check(channel, "lcr_user_rate_field", user_rate_field, SWITCH_FALSE);
|
switch_channel_set_variable_var_check(channel, "lcr_user_rate_field", user_rate_field, SWITCH_FALSE);
|
||||||
|
@ -70,23 +70,77 @@ SWITCH_STANDARD_APP(stop_dtmf_session_function)
|
|||||||
spandsp_stop_inband_dtmf_session(session);
|
spandsp_stop_inband_dtmf_session(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SWITCH_STANDARD_APP(spandsp_fax_detect_session_function)
|
||||||
|
{
|
||||||
|
int argc = 0;
|
||||||
|
char *argv[3] = { 0 };
|
||||||
|
char *dupdata;
|
||||||
|
const char *app = NULL, *arg = NULL;
|
||||||
|
int timeout = 0;
|
||||||
|
|
||||||
|
if (!zstr(data) && (dupdata = switch_core_session_strdup(session, data))) {
|
||||||
|
if ((argc = switch_split(dupdata, ' ', argv)) == 3) {
|
||||||
|
app = argv[0];
|
||||||
|
arg = argv[1];
|
||||||
|
timeout = atoi(argv[2]);
|
||||||
|
if (timeout < 0) {
|
||||||
|
timeout = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Enabling fax detection '%s' '%s'\n", argv[0], argv[1]);
|
||||||
|
spandsp_fax_detect_session(session, "rw", timeout, 1, app, arg, NULL);
|
||||||
|
} else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot Enable fax detection '%s' '%s'\n", argv[0], argv[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_STANDARD_APP(spandsp_stop_fax_detect_session_function)
|
||||||
|
{
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Disabling fax detection\n");
|
||||||
|
spandsp_fax_stop_detect_session(session);
|
||||||
|
}
|
||||||
|
|
||||||
static void event_handler(switch_event_t *event)
|
static void event_handler(switch_event_t *event)
|
||||||
{
|
{
|
||||||
mod_spandsp_fax_event_handler(event);
|
mod_spandsp_fax_event_handler(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SWITCH_STANDARD_APP(t38_gateway_function)
|
SWITCH_STANDARD_APP(t38_gateway_function)
|
||||||
{
|
{
|
||||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||||
time_t timeout = switch_epoch_time_now(NULL) + 20;
|
time_t timeout = switch_epoch_time_now(NULL) + 20;
|
||||||
const char *var;
|
const char *var;
|
||||||
|
int argc = 0;
|
||||||
|
char *argv[2] = { 0 };
|
||||||
|
char *dupdata;
|
||||||
|
const char *direction = NULL, *flags = NULL;
|
||||||
|
|
||||||
if (zstr(data) || strcasecmp(data, "self")) {
|
if (!zstr(data) && (dupdata = switch_core_session_strdup(session, data))) {
|
||||||
data = "peer";
|
if ((argc = switch_split(dupdata, ' ', argv))) {
|
||||||
|
if (argc > 0) {
|
||||||
|
direction = argv[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_channel_set_variable(channel, "t38_leg", data);
|
if (argc > 1) {
|
||||||
|
flags = argv[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zstr(direction) || strcasecmp(direction, "self")) {
|
||||||
|
direction = "peer";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_channel_set_variable(channel, "t38_leg", direction);
|
||||||
|
|
||||||
|
if (!zstr(flags) && !strcasecmp(flags, "nocng")) {
|
||||||
|
t38_gateway_start(session, direction, NULL);
|
||||||
|
} else {
|
||||||
if ((var = switch_channel_get_variable(channel, "t38_gateway_detect_timeout"))) {
|
if ((var = switch_channel_get_variable(channel, "t38_gateway_detect_timeout"))) {
|
||||||
long to = atol(var);
|
long to = atol(var);
|
||||||
if (to > -1) {
|
if (to > -1) {
|
||||||
@ -96,7 +150,9 @@ SWITCH_STANDARD_APP(t38_gateway_function)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_ivr_tone_detect_session(session, "t38", "1100.0", "rw", timeout, 1, data, NULL, t38_gateway_start);
|
//switch_ivr_tone_detect_session(session, "t38", "1100.0", "rw", timeout, 1, direction, NULL, t38_gateway_start);
|
||||||
|
spandsp_fax_detect_session(session, "rw", timeout, 1, direction, NULL, t38_gateway_start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -198,6 +254,12 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init)
|
|||||||
SWITCH_ADD_APP(app_interface, "spandsp_stop_dtmf", "stop inband dtmf", "Stop detecting inband dtmf.", stop_dtmf_session_function, "", SAF_NONE);
|
SWITCH_ADD_APP(app_interface, "spandsp_stop_dtmf", "stop inband dtmf", "Stop detecting inband dtmf.", stop_dtmf_session_function, "", SAF_NONE);
|
||||||
SWITCH_ADD_APP(app_interface, "spandsp_start_dtmf", "Detect dtmf", "Detect inband dtmf on the session", dtmf_session_function, "", SAF_MEDIA_TAP);
|
SWITCH_ADD_APP(app_interface, "spandsp_start_dtmf", "Detect dtmf", "Detect inband dtmf on the session", dtmf_session_function, "", SAF_MEDIA_TAP);
|
||||||
|
|
||||||
|
SWITCH_ADD_APP(app_interface, "spandsp_start_fax_detect", "start fax detect", "start fax detect", spandsp_fax_detect_session_function,
|
||||||
|
"<app>[ <arg>][ <timeout>]", SAF_NONE);
|
||||||
|
|
||||||
|
SWITCH_ADD_APP(app_interface, "spandsp_stop_fax_detect", "stop fax detect", "stop fax detect", spandsp_stop_fax_detect_session_function, "", SAF_NONE);
|
||||||
|
|
||||||
|
|
||||||
mod_spandsp_fax_load(pool);
|
mod_spandsp_fax_load(pool);
|
||||||
mod_spandsp_codecs_load(module_interface, pool);
|
mod_spandsp_codecs_load(module_interface, pool);
|
||||||
|
|
||||||
|
@ -68,3 +68,9 @@ switch_status_t spandsp_inband_dtmf_session(switch_core_session_t *session);
|
|||||||
|
|
||||||
switch_status_t callprogress_detector_start(switch_core_session_t *session, const char *name);
|
switch_status_t callprogress_detector_start(switch_core_session_t *session, const char *name);
|
||||||
switch_status_t callprogress_detector_stop(switch_core_session_t *session);
|
switch_status_t callprogress_detector_stop(switch_core_session_t *session);
|
||||||
|
|
||||||
|
switch_status_t spandsp_fax_detect_session(switch_core_session_t *session,
|
||||||
|
const char *flags, time_t timeout,
|
||||||
|
int hits, const char *app, const char *data, switch_tone_detect_callback_t callback);
|
||||||
|
|
||||||
|
switch_status_t spandsp_fax_stop_detect_session(switch_core_session_t *session);
|
||||||
|
@ -446,8 +446,8 @@ static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uin
|
|||||||
/* we need to build a real packet here and make write_frame.packet and write_frame.packetlen point to it */
|
/* we need to build a real packet here and make write_frame.packet and write_frame.packetlen point to it */
|
||||||
out_frame.flags = SFF_UDPTL_PACKET | SFF_PROXY_PACKET;
|
out_frame.flags = SFF_UDPTL_PACKET | SFF_PROXY_PACKET;
|
||||||
out_frame.packet = pkt;
|
out_frame.packet = pkt;
|
||||||
out_frame.packetlen = udptl_build_packet(pvt->udptl_state, pkt, buf, len);
|
if ((r = udptl_build_packet(pvt->udptl_state, pkt, buf, len)) > 0) {
|
||||||
|
out_frame.packetlen = r;
|
||||||
//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "WRITE %d udptl bytes\n", out_frame.packetlen);
|
//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "WRITE %d udptl bytes\n", out_frame.packetlen);
|
||||||
|
|
||||||
for (x = 0; x < count; x++) {
|
for (x = 0; x < count; x++) {
|
||||||
@ -456,6 +456,18 @@ static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uin
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "INVALID PACKETLEN: %d PASSED: %d:%d\n", r, len, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
t30_state_t *t30;
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "TERMINATING T30 STATE\n");
|
||||||
|
if (pvt->t38_state && (t30 = t38_terminal_get_t30_state(pvt->t38_state))) {
|
||||||
|
t30_terminate(t30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -1772,8 +1784,8 @@ switch_bool_t t38_gateway_start(switch_core_session_t *session, const char *app,
|
|||||||
switch_channel_set_variable(channel, "t38_peer", switch_core_session_get_uuid(other_session));
|
switch_channel_set_variable(channel, "t38_peer", switch_core_session_get_uuid(other_session));
|
||||||
switch_channel_set_variable(other_channel, "t38_peer", switch_core_session_get_uuid(session));
|
switch_channel_set_variable(other_channel, "t38_peer", switch_core_session_get_uuid(session));
|
||||||
|
|
||||||
switch_channel_set_variable(peer ? other_channel : channel, "t38_gateway_format", "audio");
|
switch_channel_set_variable(peer ? other_channel : channel, "t38_gateway_format", "udptl");
|
||||||
switch_channel_set_variable(peer ? channel : other_channel, "t38_gateway_format", "udptl");
|
switch_channel_set_variable(peer ? channel : other_channel, "t38_gateway_format", "audio");
|
||||||
|
|
||||||
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s starting gateway mode to %s\n",
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s starting gateway mode to %s\n",
|
||||||
@ -1803,6 +1815,250 @@ switch_bool_t t38_gateway_start(switch_core_session_t *session, const char *app,
|
|||||||
return SWITCH_FALSE;
|
return SWITCH_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *app;
|
||||||
|
char *data;
|
||||||
|
char *key;
|
||||||
|
int up;
|
||||||
|
int total_hits;
|
||||||
|
int hits;
|
||||||
|
int sleep;
|
||||||
|
int expires;
|
||||||
|
int default_sleep;
|
||||||
|
int default_expires;
|
||||||
|
switch_tone_detect_callback_t callback;
|
||||||
|
modem_connect_tones_rx_state_t rx_tones;
|
||||||
|
|
||||||
|
switch_media_bug_t *bug;
|
||||||
|
switch_core_session_t *session;
|
||||||
|
int bug_running;
|
||||||
|
|
||||||
|
} spandsp_fax_tone_container_t;
|
||||||
|
|
||||||
|
static switch_status_t tone_on_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf, switch_dtmf_direction_t direction)
|
||||||
|
{
|
||||||
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||||
|
spandsp_fax_tone_container_t *cont = switch_channel_get_private(channel, "_fax_tone_detect_");
|
||||||
|
|
||||||
|
|
||||||
|
if (!cont || dtmf->digit != 'f') {
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cont->callback) {
|
||||||
|
cont->callback(cont->session, cont->app, cont->data);
|
||||||
|
} else {
|
||||||
|
switch_channel_execute_on(switch_core_session_get_channel(cont->session), "execute_on_fax_detect");
|
||||||
|
if (cont->app) {
|
||||||
|
switch_core_session_execute_application_async(cont->session, cont->app, cont->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static switch_bool_t tone_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
|
||||||
|
{
|
||||||
|
spandsp_fax_tone_container_t *cont = (spandsp_fax_tone_container_t *) user_data;
|
||||||
|
switch_frame_t *frame = NULL;
|
||||||
|
switch_bool_t rval = SWITCH_TRUE;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case SWITCH_ABC_TYPE_INIT:
|
||||||
|
if (cont) {
|
||||||
|
cont->bug_running = 1;
|
||||||
|
modem_connect_tones_rx_init(&cont->rx_tones, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, NULL, NULL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SWITCH_ABC_TYPE_CLOSE:
|
||||||
|
break;
|
||||||
|
case SWITCH_ABC_TYPE_READ_REPLACE:
|
||||||
|
case SWITCH_ABC_TYPE_WRITE_REPLACE:
|
||||||
|
{
|
||||||
|
int skip = 0;
|
||||||
|
|
||||||
|
if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
|
||||||
|
frame = switch_core_media_bug_get_read_replace_frame(bug);
|
||||||
|
} else {
|
||||||
|
frame = switch_core_media_bug_get_write_replace_frame(bug);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cont->sleep) {
|
||||||
|
cont->sleep--;
|
||||||
|
if (cont->sleep) {
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cont->expires) {
|
||||||
|
cont->expires--;
|
||||||
|
if (!cont->expires) {
|
||||||
|
cont->hits = 0;
|
||||||
|
cont->sleep = 0;
|
||||||
|
cont->expires = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cont->up) {
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skip) {
|
||||||
|
return SWITCH_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cont->hits = 0;
|
||||||
|
modem_connect_tones_rx(&cont->rx_tones, frame->data, frame->samples);
|
||||||
|
cont->hits = modem_connect_tones_rx_get(&cont->rx_tones);
|
||||||
|
|
||||||
|
if (cont->hits) {
|
||||||
|
switch_event_t *event;
|
||||||
|
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_DEBUG,
|
||||||
|
"Fax Tone Detected. [%s][%s]\n", cont->app, switch_str_nil(cont->data));
|
||||||
|
|
||||||
|
if (cont->callback) {
|
||||||
|
cont->callback(cont->session, cont->app, cont->data);
|
||||||
|
} else {
|
||||||
|
switch_channel_execute_on(switch_core_session_get_channel(cont->session), "execute_on_fax_detect");
|
||||||
|
if (cont->app) {
|
||||||
|
switch_core_session_execute_application_async(cont->session, cont->app, cont->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (switch_event_create(&event, SWITCH_EVENT_DETECTED_TONE) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_event_t *dup;
|
||||||
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detected-Fax-Tone", "true");
|
||||||
|
|
||||||
|
if (switch_event_dup(&dup, event) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_event_fire(&dup);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_core_session_queue_event(cont->session, &event) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR,
|
||||||
|
"Event queue failed!\n");
|
||||||
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true");
|
||||||
|
switch_event_fire(&event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rval = SWITCH_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SWITCH_ABC_TYPE_WRITE:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rval == SWITCH_FALSE) {
|
||||||
|
cont->bug_running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_status_t spandsp_fax_stop_detect_session(switch_core_session_t *session)
|
||||||
|
{
|
||||||
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||||
|
spandsp_fax_tone_container_t *cont = switch_channel_get_private(channel, "_fax_tone_detect_");
|
||||||
|
|
||||||
|
if (cont) {
|
||||||
|
switch_channel_set_private(channel, "_fax_tone_detect_", NULL);
|
||||||
|
cont->up = 0;
|
||||||
|
switch_core_media_bug_remove(session, &cont->bug);
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_status_t spandsp_fax_detect_session(switch_core_session_t *session,
|
||||||
|
const char *flags, time_t timeout,
|
||||||
|
int hits, const char *app, const char *data, switch_tone_detect_callback_t callback)
|
||||||
|
{
|
||||||
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||||
|
switch_status_t status;
|
||||||
|
spandsp_fax_tone_container_t *cont = switch_channel_get_private(channel, "_fax_tone_detect_");
|
||||||
|
switch_media_bug_flag_t bflags = 0;
|
||||||
|
const char *var;
|
||||||
|
switch_codec_implementation_t read_impl = { 0 };
|
||||||
|
switch_core_session_get_read_impl(session, &read_impl);
|
||||||
|
|
||||||
|
if (cont) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Max Tones Reached!\n");
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cont && !(cont = switch_core_session_alloc(session, sizeof(*cont)))) {
|
||||||
|
return SWITCH_STATUS_MEMERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app) {
|
||||||
|
cont->app = switch_core_session_strdup(session, app);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
cont->data = switch_core_session_strdup(session, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
cont->callback = callback;
|
||||||
|
cont->up = 1;
|
||||||
|
cont->session = session;
|
||||||
|
|
||||||
|
if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cont->default_sleep = 25;
|
||||||
|
cont->default_expires = 250;
|
||||||
|
|
||||||
|
if ((var = switch_channel_get_variable(channel, "fax_tone_detect_sleep"))) {
|
||||||
|
int tmp = atoi(var);
|
||||||
|
if (tmp > 0) {
|
||||||
|
cont->default_sleep = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((var = switch_channel_get_variable(channel, "fax_tone_detect_expires"))) {
|
||||||
|
int tmp = atoi(var);
|
||||||
|
if (tmp > 0) {
|
||||||
|
cont->default_expires = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zstr(flags)) {
|
||||||
|
bflags = SMBF_READ_REPLACE;
|
||||||
|
} else {
|
||||||
|
if (strchr(flags, 'r')) {
|
||||||
|
bflags |= SMBF_READ_REPLACE;
|
||||||
|
} else if (strchr(flags, 'w')) {
|
||||||
|
bflags |= SMBF_WRITE_REPLACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bflags |= SMBF_NO_PAUSE;
|
||||||
|
|
||||||
|
|
||||||
|
switch_core_event_hook_add_send_dtmf(session, tone_on_dtmf);
|
||||||
|
switch_core_event_hook_add_recv_dtmf(session, tone_on_dtmf);
|
||||||
|
|
||||||
|
|
||||||
|
if ((status = switch_core_media_bug_add(session, "fax_tone_detect", "",
|
||||||
|
tone_detect_callback, cont, timeout, bflags, &cont->bug)) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
cont->bug_running = 0;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_channel_set_private(channel, "_fax_tone_detect_", cont);
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* For Emacs:
|
/* For Emacs:
|
||||||
|
@ -65,6 +65,14 @@ typedef struct {
|
|||||||
} cepstral_t;
|
} cepstral_t;
|
||||||
|
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
char *encoding;
|
||||||
|
} globals;
|
||||||
|
|
||||||
|
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_encoding, globals.encoding);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This callback caches the audio in the buffer */
|
/* This callback caches the audio in the buffer */
|
||||||
static swift_result_t write_audio(swift_event * event, swift_event_t type, void *udata)
|
static swift_result_t write_audio(swift_event * event, swift_event_t type, void *udata)
|
||||||
{
|
{
|
||||||
@ -223,7 +231,7 @@ static switch_status_t cepstral_speech_feed_tts(switch_speech_handle_t *sh, char
|
|||||||
if (zstr(text)) {
|
if (zstr(text)) {
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
swift_port_speak_file(cepstral->port, text, NULL, &cepstral->tts_stream, NULL);
|
swift_port_speak_file(cepstral->port, text, globals.encoding, &cepstral->tts_stream, NULL);
|
||||||
} else {
|
} else {
|
||||||
char *to_say;
|
char *to_say;
|
||||||
if (zstr(text)) {
|
if (zstr(text)) {
|
||||||
@ -231,7 +239,7 @@ static switch_status_t cepstral_speech_feed_tts(switch_speech_handle_t *sh, char
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((to_say = switch_mprintf("<break time=\"1000ms\"/> %s <break time=\"1000ms\"/>", text))) {
|
if ((to_say = switch_mprintf("<break time=\"1000ms\"/> %s <break time=\"1000ms\"/>", text))) {
|
||||||
swift_port_speak_text(cepstral->port, to_say, 0, NULL, &cepstral->tts_stream, NULL);
|
swift_port_speak_text(cepstral->port, to_say, 0, globals.encoding, &cepstral->tts_stream, NULL);
|
||||||
switch_safe_free(to_say);
|
switch_safe_free(to_say);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -401,10 +409,54 @@ static void cepstral_float_param_tts(switch_speech_handle_t *sh, char *param, do
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static switch_status_t load_config(void)
|
||||||
|
{
|
||||||
|
char *cf = "cepstral.conf";
|
||||||
|
switch_xml_t cfg, xml = NULL, param, settings;
|
||||||
|
|
||||||
|
/* Init to SWIFT default encoding */
|
||||||
|
set_global_encoding(SWIFT_DEFAULT_ENCODING);
|
||||||
|
|
||||||
|
if (xml = switch_xml_open_cfg(cf, &cfg, NULL)) {
|
||||||
|
if ((settings = switch_xml_child(cfg, "settings"))) {
|
||||||
|
for (param = switch_xml_child(settings, "param"); param; param = param->next) {
|
||||||
|
char *var = (char *) switch_xml_attr_soft(param, "name");
|
||||||
|
char *val = (char *) switch_xml_attr_soft(param, "value");
|
||||||
|
if (!strcasecmp(var, "encoding")) {
|
||||||
|
if (!strcasecmp(val, "utf-8")) {
|
||||||
|
set_global_encoding(SWIFT_UTF8);
|
||||||
|
} else if (!strcasecmp(val, "us-ascii")) {
|
||||||
|
set_global_encoding(SWIFT_ASCII);
|
||||||
|
} else if (!strcasecmp(val, "iso8859-1")) {
|
||||||
|
set_global_encoding(SWIFT_ISO_8859_1);
|
||||||
|
} else if (!strcasecmp(val, "iso8859-15")) {
|
||||||
|
set_global_encoding(SWIFT_ISO_8859_15);
|
||||||
|
} else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown value \"%s\" for param \"%s\". Setting to default.\n", val, var);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Param \"%s\" unknown\n", var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Open of \"%s\" failed. Using default settings.\n", cf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xml) {
|
||||||
|
switch_xml_free(xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
SWITCH_MODULE_LOAD_FUNCTION(mod_cepstral_load)
|
SWITCH_MODULE_LOAD_FUNCTION(mod_cepstral_load)
|
||||||
{
|
{
|
||||||
switch_speech_interface_t *speech_interface;
|
switch_speech_interface_t *speech_interface;
|
||||||
|
|
||||||
|
memset(&globals, 0, sizeof(globals));
|
||||||
|
load_config();
|
||||||
|
|
||||||
/* Open the Swift TTS Engine */
|
/* Open the Swift TTS Engine */
|
||||||
if (!(engine = swift_engine_open(NULL))) {
|
if (!(engine = swift_engine_open(NULL))) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open Swift Engine.");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open Swift Engine.");
|
||||||
|
@ -1662,9 +1662,6 @@ static void switch_load_core_config(const char *file)
|
|||||||
switch_time_set_monotonic(switch_true(val));
|
switch_time_set_monotonic(switch_true(val));
|
||||||
} else if (!strcasecmp(var, "enable-softtimer-timerfd")) {
|
} else if (!strcasecmp(var, "enable-softtimer-timerfd")) {
|
||||||
switch_time_set_timerfd(switch_true(val));
|
switch_time_set_timerfd(switch_true(val));
|
||||||
if (switch_true(val)) {
|
|
||||||
switch_clear_flag((&runtime), SCF_CALIBRATE_CLOCK);
|
|
||||||
}
|
|
||||||
} else if (!strcasecmp(var, "enable-clock-nanosleep")) {
|
} else if (!strcasecmp(var, "enable-clock-nanosleep")) {
|
||||||
switch_time_set_nanosleep(switch_true(val));
|
switch_time_set_nanosleep(switch_true(val));
|
||||||
} else if (!strcasecmp(var, "enable-cond-yield")) {
|
} else if (!strcasecmp(var, "enable-cond-yield")) {
|
||||||
|
@ -658,7 +658,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_decode(switch_codec_t *codec,
|
|||||||
|
|
||||||
if (frames && codec->implementation->decoded_bytes_per_packet * frames > *decoded_data_len) {
|
if (frames && codec->implementation->decoded_bytes_per_packet * frames > *decoded_data_len) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Buffer size sanity check failed!\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Buffer size sanity check failed!\n");
|
||||||
return SWITCH_STATUS_GENERR;
|
*decoded_data_len = codec->implementation->decoded_bytes_per_packet;
|
||||||
|
memset(decoded_data, 255, *decoded_data_len);
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1642,18 +1642,12 @@ static char create_registrations_sql[] =
|
|||||||
SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, const char *realm, const char *token, const char *url, uint32_t expires,
|
SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, const char *realm, const char *token, const char *url, uint32_t expires,
|
||||||
const char *network_ip, const char *network_port, const char *network_proto)
|
const char *network_ip, const char *network_port, const char *network_proto)
|
||||||
{
|
{
|
||||||
switch_cache_db_handle_t *dbh;
|
|
||||||
char *sql;
|
char *sql;
|
||||||
|
|
||||||
if (!switch_test_flag((&runtime), SCF_USE_SQL)) {
|
if (!switch_test_flag((&runtime), SCF_USE_SQL)) {
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switch_core_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) {
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
|
|
||||||
return SWITCH_STATUS_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runtime.multiple_registrations) {
|
if (runtime.multiple_registrations) {
|
||||||
sql = switch_mprintf("delete from registrations where hostname='%q' and (url='%q' or token='%q')",
|
sql = switch_mprintf("delete from registrations where hostname='%q' and (url='%q' or token='%q')",
|
||||||
switch_core_get_hostname(), url, switch_str_nil(token));
|
switch_core_get_hostname(), url, switch_str_nil(token));
|
||||||
@ -1662,8 +1656,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, c
|
|||||||
user, realm, switch_core_get_hostname());
|
user, realm, switch_core_get_hostname());
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_cache_db_execute_sql(dbh, sql, NULL);
|
switch_queue_push(sql_manager.sql_queue[0], sql);
|
||||||
free(sql);
|
|
||||||
|
|
||||||
sql = switch_mprintf("insert into registrations (reg_user,realm,token,url,expires,network_ip,network_port,network_proto,hostname) "
|
sql = switch_mprintf("insert into registrations (reg_user,realm,token,url,expires,network_ip,network_port,network_proto,hostname) "
|
||||||
"values ('%q','%q','%q','%q',%ld,'%q','%q','%q','%q')",
|
"values ('%q','%q','%q','%q',%ld,'%q','%q','%q','%q')",
|
||||||
@ -1678,10 +1671,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, c
|
|||||||
switch_core_get_hostname()
|
switch_core_get_hostname()
|
||||||
);
|
);
|
||||||
|
|
||||||
switch_cache_db_execute_sql(dbh, sql, NULL);
|
|
||||||
switch_cache_db_release_db_handle(&dbh);
|
|
||||||
|
|
||||||
free(sql);
|
switch_queue_push(sql_manager.sql_queue[0], sql);
|
||||||
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1689,28 +1680,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, c
|
|||||||
SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, const char *realm, const char *token)
|
SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, const char *realm, const char *token)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch_cache_db_handle_t *dbh;
|
|
||||||
char *sql;
|
char *sql;
|
||||||
|
|
||||||
if (!switch_test_flag((&runtime), SCF_USE_SQL)) {
|
if (!switch_test_flag((&runtime), SCF_USE_SQL)) {
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switch_core_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) {
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
|
|
||||||
return SWITCH_STATUS_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!zstr(token) && runtime.multiple_registrations) {
|
if (!zstr(token) && runtime.multiple_registrations) {
|
||||||
sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q' and token='%q'", user, realm, switch_core_get_hostname(), token);
|
sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q' and token='%q'", user, realm, switch_core_get_hostname(), token);
|
||||||
} else {
|
} else {
|
||||||
sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q'", user, realm, switch_core_get_hostname());
|
sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q'", user, realm, switch_core_get_hostname());
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_cache_db_execute_sql(dbh, sql, NULL);
|
switch_queue_push(sql_manager.sql_queue[0], sql);
|
||||||
switch_cache_db_release_db_handle(&dbh);
|
|
||||||
|
|
||||||
free(sql);
|
|
||||||
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1718,7 +1700,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, c
|
|||||||
SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force)
|
SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch_cache_db_handle_t *dbh;
|
|
||||||
char *sql;
|
char *sql;
|
||||||
time_t now;
|
time_t now;
|
||||||
|
|
||||||
@ -1726,11 +1707,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force)
|
|||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switch_core_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) {
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
|
|
||||||
return SWITCH_STATUS_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
now = switch_epoch_time_now(NULL);
|
now = switch_epoch_time_now(NULL);
|
||||||
|
|
||||||
if (force) {
|
if (force) {
|
||||||
@ -1739,10 +1715,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force)
|
|||||||
sql = switch_mprintf("delete from registrations where expires > 0 and expires <= %ld and hostname='%q'", now, switch_core_get_hostname());
|
sql = switch_mprintf("delete from registrations where expires > 0 and expires <= %ld and hostname='%q'", now, switch_core_get_hostname());
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_cache_db_execute_sql(dbh, sql, NULL);
|
switch_queue_push(sql_manager.sql_queue[0], sql);
|
||||||
switch_cache_db_release_db_handle(&dbh);
|
|
||||||
|
|
||||||
free(sql);
|
|
||||||
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
@ -586,7 +586,7 @@ SWITCH_DECLARE(switch_status_t) switch_nat_add_mapping_internal(switch_port_t po
|
|||||||
switch_event_t *event = NULL;
|
switch_event_t *event = NULL;
|
||||||
|
|
||||||
if (!nat_globals.mapping) {
|
if (!nat_globals.mapping) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "NAT port mapping disabled\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "NAT port mapping disabled\n");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,14 +61,20 @@ static int MONO = 1;
|
|||||||
static int MONO = 0;
|
static int MONO = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* clock_nanosleep works badly on some kernels but really well on others.
|
||||||
|
timerfd seems to work well as long as it exists so if you have timerfd we'll also enable clock_nanosleep by default.
|
||||||
|
*/
|
||||||
#if defined(HAVE_TIMERFD_CREATE)
|
#if defined(HAVE_TIMERFD_CREATE)
|
||||||
// We'll default this to 1 after we have had some positive feedback that it works well
|
static int TFD = 1;
|
||||||
static int TFD = 0;
|
#if defined(HAVE_CLOCK_NANOSLEEP)
|
||||||
|
static int NANO = 1;
|
||||||
|
#else
|
||||||
|
static int NANO = 0;
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
static int TFD = 0;
|
static int TFD = 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
static int NANO = 0;
|
static int NANO = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
static int OFFSET = 0;
|
static int OFFSET = 0;
|
||||||
|
|
||||||
@ -326,6 +332,7 @@ SWITCH_DECLARE(void) switch_time_set_timerfd(switch_bool_t enable)
|
|||||||
#if defined(HAVE_TIMERFD_CREATE)
|
#if defined(HAVE_TIMERFD_CREATE)
|
||||||
TFD = enable ? 1 : 0;
|
TFD = enable ? 1 : 0;
|
||||||
switch_time_sync();
|
switch_time_sync();
|
||||||
|
|
||||||
#else
|
#else
|
||||||
TFD = 0;
|
TFD = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -1116,6 +1123,10 @@ SWITCH_MODULE_LOAD_FUNCTION(softtimer_load)
|
|||||||
switch_time_set_cond_yield(SWITCH_FALSE);
|
switch_time_set_cond_yield(SWITCH_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TFD) {
|
||||||
|
switch_clear_flag((&runtime), SCF_CALIBRATE_CLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
if (switch_test_flag((&runtime), SCF_CALIBRATE_CLOCK)) {
|
if (switch_test_flag((&runtime), SCF_CALIBRATE_CLOCK)) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Calibrating timer, please wait...\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Calibrating timer, please wait...\n");
|
||||||
switch_time_calibrate_clock();
|
switch_time_calibrate_clock();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user