mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-14 23:34:13 +00:00
Merge branch 'master' into smgmaster
This commit is contained in:
commit
2b8d96a301
364 files changed
+122942
-1699
No files matched your search
@@ -150,6 +150,7 @@
|
||||
*
|
||||
* - Linux (x86 & x86_64)
|
||||
* - Windows (MSVC 2008 & VC++ EE 2008)
|
||||
* - Windows (MSVC 2010 & VC++ EE 2010)
|
||||
* - Mac OS X (intel & ppc )
|
||||
* - FreeBSD 6
|
||||
*
|
||||
@@ -176,6 +177,10 @@
|
||||
* mod_pocketsphinx
|
||||
* - PocketSphinx (http://www.speech.cs.cmu.edu/pocketsphinx/)
|
||||
*
|
||||
* mod_unimrcp
|
||||
* - MRCP (http://www.unimrcp.org/)
|
||||
*
|
||||
*
|
||||
* Codecs
|
||||
* mod_speex
|
||||
* - libspeex (http://www.speex.org/)
|
||||
|
||||
@@ -145,6 +145,8 @@ SWITCH_DECLARE(int) switch_snprintf(_Out_z_cap_(len)
|
||||
|
||||
SWITCH_DECLARE(int) switch_vasprintf(_Out_opt_ char **buf, _In_z_ _Printf_format_string_ const char *format, _In_ va_list ap);
|
||||
|
||||
SWITCH_DECLARE(int) switch_vsnprintf(char *buf, switch_size_t len, const char *format, va_list ap);
|
||||
|
||||
SWITCH_DECLARE(char *) switch_copy_string(_Out_z_cap_(dst_size)
|
||||
char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size);
|
||||
|
||||
|
||||
@@ -615,6 +615,9 @@ SWITCH_DECLARE(void) switch_channel_mark_hold(switch_channel_t *channel, switch_
|
||||
|
||||
/** @} */
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix);
|
||||
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
#endif
|
||||
/* For Emacs:
|
||||
|
||||
@@ -1183,7 +1183,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(_In_ switch_core_s
|
||||
///\ingroup core1
|
||||
///\{
|
||||
/*!
|
||||
\brief Initilize a hash table
|
||||
\brief Initialize a hash table
|
||||
\param hash a NULL pointer to a hash table to aim at the new hash
|
||||
\param pool the pool to use for the new hash
|
||||
\return SWITCH_STATUS_SUCCESS if the hash is created
|
||||
@@ -2240,6 +2240,15 @@ 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(char *) switch_say_file_handle_get_variable(switch_say_file_handle_t *sh, const char *var);
|
||||
SWITCH_DECLARE(char *) switch_say_file_handle_get_path(switch_say_file_handle_t *sh);
|
||||
SWITCH_DECLARE(char *) switch_say_file_handle_detach_path(switch_say_file_handle_t *sh);
|
||||
SWITCH_DECLARE(void) switch_say_file_handle_destroy(switch_say_file_handle_t **sh);
|
||||
SWITCH_DECLARE(switch_status_t) switch_say_file_handle_create(switch_say_file_handle_t **sh, const char *ext, switch_event_t **var_event);
|
||||
SWITCH_DECLARE(void) switch_say_file(switch_say_file_handle_t *sh, const char *fmt, ...);
|
||||
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
#endif
|
||||
/* For Emacs:
|
||||
|
||||
@@ -859,6 +859,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
|
||||
const char *say_gender,
|
||||
switch_input_args_t *args);
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_ivr_say_string(switch_core_session_t *session,
|
||||
const char *lang,
|
||||
const char *ext,
|
||||
const char *tosay,
|
||||
const char *module_name,
|
||||
const char *say_type,
|
||||
const char *say_method,
|
||||
const char *say_gender,
|
||||
char **rstr);
|
||||
|
||||
SWITCH_DECLARE(switch_say_method_t) switch_ivr_get_say_method_by_name(const char *name);
|
||||
SWITCH_DECLARE(switch_say_gender_t) switch_ivr_get_say_gender_by_name(const char *name);
|
||||
SWITCH_DECLARE(switch_say_type_t) switch_ivr_get_say_type_by_name(const char *name);
|
||||
|
||||
@@ -103,29 +103,9 @@ struct switch_stream_handle {
|
||||
};
|
||||
|
||||
struct switch_io_event_hooks;
|
||||
struct switch_say_file_handle;
|
||||
|
||||
|
||||
|
||||
typedef switch_call_cause_t (*switch_io_outgoing_channel_t)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef switch_call_cause_t (*switch_io_outgoing_channel_t)
|
||||
(switch_core_session_t *, switch_event_t *, switch_caller_profile_t *, switch_core_session_t **, switch_memory_pool_t **, switch_originate_flag_t,
|
||||
switch_call_cause_t *);
|
||||
typedef switch_status_t (*switch_io_read_frame_t) (switch_core_session_t *, switch_frame_t **, switch_io_flag_t, int);
|
||||
@@ -490,6 +470,7 @@ struct switch_say_interface {
|
||||
const char *interface_name;
|
||||
/*! function to pass down to the module */
|
||||
switch_say_callback_t say_function;
|
||||
switch_say_string_callback_t say_string_function;
|
||||
switch_thread_rwlock_t *rwlock;
|
||||
int refs;
|
||||
switch_mutex_t *reflock;
|
||||
|
||||
@@ -56,7 +56,7 @@ SWITCH_DECLARE(const char *) switch_nat_get_type(void);
|
||||
\param pool the memory pool to use for long term allocations
|
||||
\note Generally called by the core_init
|
||||
*/
|
||||
SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool);
|
||||
SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool, switch_bool_t mapping);
|
||||
|
||||
/*!
|
||||
\brief Initilize the rest of the NAT Traversal System
|
||||
@@ -86,6 +86,11 @@ SWITCH_DECLARE(void) switch_nat_republish(void);
|
||||
*/
|
||||
SWITCH_DECLARE(void) switch_nat_reinit(void);
|
||||
|
||||
/*!
|
||||
\brief Update the setting if port mapping will be created
|
||||
*/
|
||||
SWITCH_DECLARE(void) switch_nat_set_mapping(switch_bool_t mapping);
|
||||
|
||||
/*!
|
||||
\brief Maps a port through the NAT Traversal System
|
||||
\param port Internal port to map
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#define SWITCH_TYPES_H
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
SWITCH_BEGIN_EXTERN_C
|
||||
#define SWITCH_ENT_ORIGINATE_DELIM ":_:"
|
||||
#define SWITCH_BLANK_STRING ""
|
||||
@@ -264,7 +265,8 @@ typedef enum {
|
||||
SCF_VERBOSE_EVENTS = (1 << 11),
|
||||
SCF_USE_WIN32_MONOTONIC = (1 << 12),
|
||||
SCF_AUTO_SCHEMAS = (1 << 13),
|
||||
SCF_MINIMAL = (1 << 14)
|
||||
SCF_MINIMAL = (1 << 14),
|
||||
SCF_USE_NAT_MAPPING = (1 << 15)
|
||||
} switch_core_flag_enum_t;
|
||||
typedef uint32_t switch_core_flag_t;
|
||||
|
||||
@@ -515,7 +517,6 @@ typedef enum {
|
||||
SWITCH_RTP_FLAG_NOBLOCK - Do not block
|
||||
SWITCH_RTP_FLAG_IO - IO is ready
|
||||
SWITCH_RTP_FLAG_USE_TIMER - Timeout Reads and replace with a CNG Frame
|
||||
SWITCH_RTP_FLAG_TIMER_RECLOCK - Resync the timer to the current clock on slips
|
||||
SWITCH_RTP_FLAG_SECURE - Secure RTP
|
||||
SWITCH_RTP_FLAG_AUTOADJ - Auto-Adjust the dest based on the source
|
||||
SWITCH_RTP_FLAG_RAW_WRITE - Try to forward packets unscathed
|
||||
@@ -532,7 +533,7 @@ typedef enum {
|
||||
SWITCH_RTP_FLAG_NOBLOCK = (1 << 0),
|
||||
SWITCH_RTP_FLAG_IO = (1 << 1),
|
||||
SWITCH_RTP_FLAG_USE_TIMER = (1 << 2),
|
||||
SWITCH_RTP_FLAG_TIMER_RECLOCK = (1 << 3),
|
||||
SWITCH_RTP_FLAG_RTCP_PASSTHRU = (1 << 3),
|
||||
SWITCH_RTP_FLAG_SECURE_SEND = (1 << 4),
|
||||
SWITCH_RTP_FLAG_SECURE_RECV = (1 << 5),
|
||||
SWITCH_RTP_FLAG_AUTOADJ = (1 << 6),
|
||||
@@ -559,8 +560,7 @@ typedef enum {
|
||||
SWITCH_RTP_FLAG_DEBUG_RTP_READ = (1 << 27),
|
||||
SWITCH_RTP_FLAG_DEBUG_RTP_WRITE = (1 << 28),
|
||||
SWITCH_RTP_FLAG_VIDEO = (1 << 29),
|
||||
SWITCH_RTP_FLAG_ENABLE_RTCP = (1 << 30),
|
||||
SWITCH_RTP_FLAG_RTCP_PASSTHRU = (1 << 31)
|
||||
SWITCH_RTP_FLAG_ENABLE_RTCP = (1 << 30)
|
||||
/* don't add any more 31 is the limit! gotta chnge to an array to add more */
|
||||
} switch_rtp_flag_enum_t;
|
||||
typedef uint32_t switch_rtp_flag_t;
|
||||
@@ -1737,6 +1737,7 @@ typedef switch_status_t (*switch_stream_handle_raw_write_function_t) (switch_str
|
||||
typedef switch_status_t (*switch_api_function_t) (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session,
|
||||
_In_ switch_stream_handle_t *stream);
|
||||
|
||||
|
||||
#define SWITCH_STANDARD_API(name) static switch_status_t name (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream)
|
||||
|
||||
typedef switch_status_t (*switch_input_callback_function_t) (switch_core_session_t *session, void *input,
|
||||
@@ -1774,17 +1775,32 @@ typedef struct {
|
||||
switch_ivr_dmachine_t *dmachine;
|
||||
} switch_input_args_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
switch_say_type_t type;
|
||||
switch_say_method_t method;
|
||||
switch_say_gender_t gender;
|
||||
const char *ext;
|
||||
} switch_say_args_t;
|
||||
|
||||
|
||||
typedef switch_status_t (*switch_say_callback_t) (switch_core_session_t *session,
|
||||
char *tosay,
|
||||
switch_say_args_t *say_args,
|
||||
switch_input_args_t *args);
|
||||
|
||||
typedef switch_status_t (*switch_say_string_callback_t) (switch_core_session_t *session,
|
||||
char *tosay,
|
||||
switch_say_args_t *say_args, char **rstr);
|
||||
|
||||
struct switch_say_file_handle;
|
||||
typedef struct switch_say_file_handle switch_say_file_handle_t;
|
||||
|
||||
typedef switch_status_t (*switch_new_say_callback_t) (switch_say_file_handle_t *sh,
|
||||
char *tosay,
|
||||
switch_say_args_t *say_args);
|
||||
|
||||
|
||||
typedef struct switch_xml *switch_xml_t;
|
||||
typedef struct switch_core_time_duration switch_core_time_duration_t;
|
||||
typedef switch_xml_t(*switch_xml_search_function_t) (const char *section,
|
||||
|
||||
@@ -151,7 +151,11 @@ static inline char *switch_strchr_strict(const char *in, char find, const char *
|
||||
#endif
|
||||
static inline int switch_string_has_escaped_data(const char *in)
|
||||
{
|
||||
const char *i = strchr(in, '\\');
|
||||
const char *i;
|
||||
|
||||
switch_assert(in);
|
||||
|
||||
i = strchr(in, '\\');
|
||||
|
||||
while (i && *i == '\\') {
|
||||
i++;
|
||||
@@ -631,7 +635,7 @@ SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in);
|
||||
#define switch_time_from_sec(sec) ((switch_time_t)(sec) * 1000000)
|
||||
|
||||
/*!
|
||||
\brief Declares a function designed to set a dymaic global string
|
||||
\brief Declares a function designed to set a dynamic global string
|
||||
\param fname the function name to declare
|
||||
\param vname the name of the global pointer to modify with the new function
|
||||
*/
|
||||
@@ -639,9 +643,9 @@ SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in);
|
||||
if (vname) {free(vname); vname = NULL;}vname = strdup(string);} static void fname(const char *string)
|
||||
|
||||
/*!
|
||||
\brief Separate a string into an array based on a character delimeter
|
||||
\brief Separate a string into an array based on a character delimiter
|
||||
\param buf the string to parse
|
||||
\param delim the character delimeter
|
||||
\param delim the character delimiter
|
||||
\param array the array to split the values into
|
||||
\param arraylen the max number of elements in the array
|
||||
\return the number of elements added to the array
|
||||
|
||||
@@ -98,6 +98,7 @@ struct switch_xml {
|
||||
uint32_t flags;
|
||||
/*! is_switch_xml_root bool */
|
||||
switch_bool_t is_switch_xml_root_t;
|
||||
uint32_t refs;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@@ -177,8 +177,9 @@ static char members_sql[] =
|
||||
" queue VARCHAR(255),\n"
|
||||
" system VARCHAR(255),\n"
|
||||
" uuid VARCHAR(255) NOT NULL DEFAULT '',\n"
|
||||
" caller_number VARCHAR(255),\n"
|
||||
" caller_name VARCHAR(255),\n"
|
||||
" session_uuid VARCHAR(255) NOT NULL DEFAULT '',\n"
|
||||
" cid_number VARCHAR(255),\n"
|
||||
" cid_name VARCHAR(255),\n"
|
||||
" system_epoch INTEGER NOT NULL DEFAULT 0,\n"
|
||||
" joined_epoch INTEGER NOT NULL DEFAULT 0,\n"
|
||||
" rejoined_epoch INTEGER NOT NULL DEFAULT 0,\n"
|
||||
@@ -704,7 +705,7 @@ static cc_queue_t *load_queue(const char *queue_name)
|
||||
goto end;
|
||||
}
|
||||
|
||||
switch_cache_db_test_reactive(dbh, "select count(rejoined_epoch) from members", "drop table members", members_sql);
|
||||
switch_cache_db_test_reactive(dbh, "select count(session_uuid) from members", "drop table members", members_sql);
|
||||
switch_cache_db_test_reactive(dbh, "select count(ready_time) from agents", NULL, "alter table agents add ready_time integer not null default 0;"
|
||||
"alter table agents add reject_delay_time integer not null default 0;"
|
||||
"alter table agents add busy_delay_time integer not null default 0;");
|
||||
@@ -718,7 +719,7 @@ static cc_queue_t *load_queue(const char *queue_name)
|
||||
/* Reset a unclean shutdown */
|
||||
sql = switch_mprintf("UPDATE agents SET state = 'Waiting', uuid = '' WHERE system = 'single_box';"
|
||||
"UPDATE tiers SET state = 'Ready' WHERE agent IN (SELECT name FROM agents WHERE system = 'single_box');"
|
||||
"UPDATE members SET state = '%q', uuid = '' WHERE system = 'single_box';",
|
||||
"UPDATE members SET state = '%q', session_uuid = '' WHERE system = 'single_box';",
|
||||
cc_member_state2str(CC_MEMBER_STATE_ABANDONED));
|
||||
|
||||
cc_execute_sql(NULL, sql, NULL);
|
||||
@@ -756,11 +757,12 @@ static cc_queue_t *get_queue(const char *queue_name)
|
||||
|
||||
struct call_helper {
|
||||
const char *member_uuid;
|
||||
const char *member_session_uuid;
|
||||
const char *queue_name;
|
||||
const char *queue_strategy;
|
||||
const char *member_joined_epoch;
|
||||
const char *member_caller_name;
|
||||
const char *member_caller_number;
|
||||
const char *member_cid_name;
|
||||
const char *member_cid_number;
|
||||
const char *agent_name;
|
||||
const char *agent_system;
|
||||
const char *agent_status;
|
||||
@@ -1356,7 +1358,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
char *sql = NULL;
|
||||
char *dialstr = NULL;
|
||||
cc_tier_state_t tiers_state = CC_TIER_STATE_READY;
|
||||
switch_core_session_t *member_session = switch_core_session_locate(h->member_uuid);
|
||||
switch_core_session_t *member_session = switch_core_session_locate(h->member_session_uuid);
|
||||
switch_event_t *ovars;
|
||||
switch_time_t t_agent_called = 0;
|
||||
switch_time_t t_agent_answered = 0;
|
||||
@@ -1369,7 +1371,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
|
||||
/* member is gone before we could process it */
|
||||
if (!member_session) {
|
||||
sql = switch_mprintf("UPDATE members SET state = '%q', uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q' AND state != '%q'",
|
||||
sql = switch_mprintf("UPDATE members SET state = '%q', session_uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q' AND state != '%q'",
|
||||
cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), h->member_uuid, cc_member_state2str(CC_MEMBER_STATE_ABANDONED));
|
||||
|
||||
cc_execute_sql(NULL, sql, NULL);
|
||||
@@ -1384,9 +1386,10 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Type", h->agent_type);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-Session-UUID", h->member_session_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Name", h->member_cid_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Number", h->member_cid_number);
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
@@ -1395,14 +1398,16 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
|
||||
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_queue", "%s", h->queue_name);
|
||||
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_uuid", "%s", h->member_uuid);
|
||||
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_session_uuid", "%s", h->member_session_uuid);
|
||||
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_pre_answer_uuid", "%s", h->member_uuid);
|
||||
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent", "%s", h->agent_name);
|
||||
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent_type", "%s", h->agent_type);
|
||||
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_side", "%s", "agent");
|
||||
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "ignore_early_media", "true");
|
||||
|
||||
t_agent_called = switch_epoch_time_now(NULL);
|
||||
dialstr = switch_mprintf("%s", h->originate_string);
|
||||
status = switch_ivr_originate(NULL, &agent_session, &cause, dialstr, 60, NULL, h->member_caller_name, h->member_caller_number, NULL, ovars, SOF_NONE, NULL);
|
||||
status = switch_ivr_originate(NULL, &agent_session, &cause, dialstr, 60, NULL, h->member_cid_name, h->member_cid_number, NULL, ovars, SOF_NONE, NULL);
|
||||
switch_safe_free(dialstr);
|
||||
|
||||
switch_event_destroy(&ovars);
|
||||
@@ -1414,10 +1419,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
switch_event_t *event;
|
||||
const char *cc_warning_tone = switch_channel_get_variable(agent_channel, "cc_warning_tone");
|
||||
|
||||
switch_channel_set_variable(agent_channel, "cc_side", "agent");
|
||||
switch_channel_set_variable(agent_channel, "cc_queue", h->queue_name);
|
||||
switch_channel_set_variable(agent_channel, "cc_agent", h->agent_name);
|
||||
switch_channel_set_variable(agent_channel, "cc_agent_type", h->agent_type);
|
||||
switch_channel_set_variable(agent_channel, "cc_member_uuid", h->member_uuid);
|
||||
switch_channel_set_variable(agent_channel, "cc_member_session_uuid", h->member_session_uuid);
|
||||
|
||||
/* Playback this to the agent */
|
||||
if (cc_warning_tone && switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
|
||||
@@ -1449,8 +1456,10 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
|
||||
/* Loopback special case */
|
||||
if (other_loopback_leg_uuid) {
|
||||
switch_core_session_t *other_loopback_session = switch_core_session_locate(other_loopback_leg_uuid);
|
||||
if (other_loopback_session) {
|
||||
switch_core_session_t *other_loopback_session = NULL;
|
||||
|
||||
switch_yield(20000); // Wait 20ms for the channel to be ready
|
||||
if ((other_loopback_session = switch_core_session_locate(other_loopback_leg_uuid))) {
|
||||
switch_channel_t *other_loopback_channel = switch_core_session_get_channel(other_loopback_session);
|
||||
const char *real_uuid = switch_channel_get_variable(other_loopback_channel, SWITCH_SIGNAL_BOND_VARIABLE);
|
||||
|
||||
@@ -1459,14 +1468,15 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
/* Switch the agent session */
|
||||
if (real_uuid) {
|
||||
switch_core_session_rwunlock(agent_session);
|
||||
agent_uuid = real_uuid;
|
||||
agent_session = switch_core_session_locate(agent_uuid);
|
||||
agent_session = switch_core_session_locate(real_uuid);
|
||||
agent_uuid = switch_core_session_get_uuid(agent_session);
|
||||
agent_channel = switch_core_session_get_channel(agent_session);
|
||||
|
||||
switch_channel_set_variable(agent_channel, "cc_queue", h->queue_name);
|
||||
switch_channel_set_variable(agent_channel, "cc_agent", h->agent_name);
|
||||
switch_channel_set_variable(agent_channel, "cc_agent_type", h->agent_type);
|
||||
switch_channel_set_variable(agent_channel, "cc_member_uuid", h->member_uuid);
|
||||
switch_channel_set_variable(agent_channel, "cc_member_session_uuid", h->member_session_uuid);
|
||||
}
|
||||
switch_core_session_rwunlock(other_loopback_session);
|
||||
}
|
||||
@@ -1508,10 +1518,11 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Joined-Time", "%ld", (long) t_member_called);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-Session-UUID", h->member_session_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Name", h->member_cid_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Number", h->member_cid_number);
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
/* for xml_cdr needs */
|
||||
@@ -1541,8 +1552,8 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s answered \"%s\" <%s> from queue %s%s\n",
|
||||
h->agent_name, h->member_caller_name, h->member_caller_number, h->queue_name, (h->record_template?" (Recorded)":""));
|
||||
switch_ivr_uuid_bridge(h->member_uuid, switch_core_session_get_uuid(agent_session));
|
||||
h->agent_name, h->member_cid_name, h->member_cid_number, h->queue_name, (h->record_template?" (Recorded)":""));
|
||||
switch_ivr_uuid_bridge(h->member_session_uuid, switch_core_session_get_uuid(agent_session));
|
||||
|
||||
/* This is used for the waiting caller to quit waiting for a agent */
|
||||
switch_channel_set_variable(member_channel, "cc_agent_uuid", agent_uuid);
|
||||
@@ -1563,11 +1574,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Joined-Time", "%ld", (long) t_member_called);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Bridge-Terminated-Time", "%ld", (long) switch_epoch_time_now(NULL));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-Session-UUID", h->member_session_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Name", h->member_cid_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Number", h->member_cid_number);
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
/* for xml_cdr needs */
|
||||
@@ -1597,11 +1609,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Joined-Time", "%ld", (long) t_member_called);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-Session-UUID", h->member_session_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Name", h->member_cid_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Number", h->member_cid_number);
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
@@ -1667,9 +1680,10 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Hangup-Cause", switch_channel_cause2str(cause));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-Session-UUID", h->member_session_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Name", h->member_cid_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Number", h->member_cid_number);
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
@@ -1711,10 +1725,12 @@ done:
|
||||
struct agent_callback {
|
||||
const char *queue_name;
|
||||
const char *system;
|
||||
const char *uuid;
|
||||
const char *caller_number;
|
||||
const char *caller_name;
|
||||
const char *joined_epoch;
|
||||
const char *member_uuid;
|
||||
const char *member_session_uuid;
|
||||
const char *member_cid_number;
|
||||
const char *member_cid_name;
|
||||
const char *member_joined_epoch;
|
||||
const char *member_score;
|
||||
const char *strategy;
|
||||
const char *record_template;
|
||||
switch_bool_t tier_rules_apply;
|
||||
@@ -1733,15 +1749,23 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
|
||||
agent_callback_t *cbt = (agent_callback_t *) pArg;
|
||||
char *sql = NULL;
|
||||
char res[256];
|
||||
char *agent_status = argv[2];
|
||||
char *agent_tier_state = argv[9];
|
||||
char *agent_last_bridge_end = argv[10];
|
||||
char *agent_wrap_up_time = argv[11];
|
||||
char *agent_state = argv[12];
|
||||
char *agent_ready_time = argv[13];
|
||||
char *agent_tier_level = argv[14];
|
||||
char *agent_type = argv[15];
|
||||
char *agent_uuid = argv[16];
|
||||
const char *agent_system = argv[0];
|
||||
const char *agent_name = argv[1];
|
||||
const char *agent_status = argv[2];
|
||||
const char *agent_originate_string = argv[3];
|
||||
const char *agent_no_answer_count = argv[4];
|
||||
const char *agent_max_no_answer = argv[5];
|
||||
const char *agent_reject_delay_time = argv[6];
|
||||
const char *agent_busy_delay_time = argv[7];
|
||||
const char *agent_no_answer_delay_time = argv[8];
|
||||
const char *agent_tier_state = argv[9];
|
||||
const char *agent_last_bridge_end = argv[10];
|
||||
const char *agent_wrap_up_time = argv[11];
|
||||
const char *agent_state = argv[12];
|
||||
const char *agent_ready_time = argv[13];
|
||||
const char *agent_tier_level = argv[14];
|
||||
const char *agent_type = argv[15];
|
||||
const char *agent_uuid = argv[16];
|
||||
|
||||
switch_bool_t contact_agent = SWITCH_TRUE;
|
||||
|
||||
@@ -1754,11 +1778,11 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
|
||||
if (cbt->tier_rule_no_agent_no_wait == SWITCH_TRUE && cbt->tier_agent_available == 0) {
|
||||
cbt->tier = atoi(agent_tier_level);
|
||||
/* Multiple the tier level by the tier wait time */
|
||||
} else if (cbt->tier_rule_wait_multiply_level == SWITCH_TRUE && (long) switch_epoch_time_now(NULL) - atol(cbt->joined_epoch) >= atoi(agent_tier_level) * cbt->tier_rule_wait_second) {
|
||||
} else if (cbt->tier_rule_wait_multiply_level == SWITCH_TRUE && (long) switch_epoch_time_now(NULL) - atol(cbt->member_joined_epoch) >= atoi(agent_tier_level) * cbt->tier_rule_wait_second) {
|
||||
cbt->tier = atoi(agent_tier_level);
|
||||
cbt->tier_agent_available = 0;
|
||||
/* Just check if joined is bigger than next tier wait time */
|
||||
} else if (cbt->tier_rule_wait_multiply_level == SWITCH_FALSE && (long) switch_epoch_time_now(NULL) - atol(cbt->joined_epoch) >= cbt->tier_rule_wait_second) {
|
||||
} else if (cbt->tier_rule_wait_multiply_level == SWITCH_FALSE && (long) switch_epoch_time_now(NULL) - atol(cbt->member_joined_epoch) >= cbt->tier_rule_wait_second) {
|
||||
cbt->tier = atoi(agent_tier_level);
|
||||
cbt->tier_agent_available = 0;
|
||||
} else {
|
||||
@@ -1790,7 +1814,7 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
|
||||
}
|
||||
|
||||
/* If agent isn't on this box */
|
||||
if (strcasecmp(argv[0],"single_box" /* SELF */)) {
|
||||
if (strcasecmp(agent_system,"single_box" /* SELF */)) {
|
||||
if (!strcasecmp(cbt->strategy, "ring-all")) {
|
||||
return 1; /* Abort finding agent for member if we found a match but for a different Server */
|
||||
} else {
|
||||
@@ -1800,7 +1824,7 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
|
||||
|
||||
if (!strcasecmp(cbt->strategy,"ring-all")) {
|
||||
/* Check if member is a ring-all mode */
|
||||
sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = 'ring-all' AND uuid = '%q' AND system = 'single_box'", cbt->uuid);
|
||||
sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = 'ring-all' AND uuid = '%q' AND system = 'single_box'", cbt->member_uuid);
|
||||
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
|
||||
|
||||
switch_safe_free(sql);
|
||||
@@ -1808,14 +1832,14 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
|
||||
/* Map the Agent to the member */
|
||||
sql = switch_mprintf("UPDATE members SET serving_agent = '%q', serving_system = 'single_box', state = '%q'"
|
||||
" WHERE state = '%q' AND uuid = '%q' AND system = 'single_box'",
|
||||
argv[1], cc_member_state2str(CC_MEMBER_STATE_TRYING),
|
||||
cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt->uuid);
|
||||
agent_name, cc_member_state2str(CC_MEMBER_STATE_TRYING),
|
||||
cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt->member_uuid);
|
||||
cc_execute_sql(NULL, sql, NULL);
|
||||
switch_safe_free(sql);
|
||||
|
||||
/* Check if we won the race to get the member to our selected agent (Used for Multi system purposes) */
|
||||
sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = '%q' AND serving_system = 'single_box' AND uuid = '%q' AND system = 'single_box'",
|
||||
argv[1], cbt->uuid);
|
||||
agent_name, cbt->member_uuid);
|
||||
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
|
||||
switch_safe_free(sql);
|
||||
}
|
||||
@@ -1834,24 +1858,25 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
|
||||
switch_core_new_memory_pool(&pool);
|
||||
h = switch_core_alloc(pool, sizeof(*h));
|
||||
h->pool = pool;
|
||||
h->member_uuid = switch_core_strdup(h->pool, cbt->uuid);
|
||||
h->member_uuid = switch_core_strdup(h->pool, cbt->member_uuid);
|
||||
h->member_session_uuid = switch_core_strdup(h->pool, cbt->member_session_uuid);
|
||||
h->queue_strategy = switch_core_strdup(h->pool, cbt->strategy);
|
||||
h->originate_string = switch_core_strdup(h->pool, argv[3]);
|
||||
h->agent_name = switch_core_strdup(h->pool, argv[1]);
|
||||
h->originate_string = switch_core_strdup(h->pool, agent_originate_string);
|
||||
h->agent_name = switch_core_strdup(h->pool, agent_name);
|
||||
h->agent_system = switch_core_strdup(h->pool, "single_box");
|
||||
h->agent_status = switch_core_strdup(h->pool, argv[2]);
|
||||
h->agent_status = switch_core_strdup(h->pool, agent_status);
|
||||
h->agent_type = switch_core_strdup(h->pool, agent_type);
|
||||
h->agent_uuid = switch_core_strdup(h->pool, agent_uuid);
|
||||
h->member_joined_epoch = switch_core_strdup(h->pool, cbt->joined_epoch);
|
||||
h->member_caller_name = switch_core_strdup(h->pool, cbt->caller_name);
|
||||
h->member_caller_number = switch_core_strdup(h->pool, cbt->caller_number);
|
||||
h->member_joined_epoch = switch_core_strdup(h->pool, cbt->member_joined_epoch);
|
||||
h->member_cid_name = switch_core_strdup(h->pool, cbt->member_cid_name);
|
||||
h->member_cid_number = switch_core_strdup(h->pool, cbt->member_cid_number);
|
||||
h->queue_name = switch_core_strdup(h->pool, cbt->queue_name);
|
||||
h->record_template = switch_core_strdup(h->pool, cbt->record_template);
|
||||
h->no_answer_count = atoi(argv[4]);
|
||||
h->max_no_answer = atoi(argv[5]);
|
||||
h->reject_delay_time = atoi(argv[6]);
|
||||
h->busy_delay_time = atoi(argv[7]);
|
||||
h->no_answer_delay_time = atoi(argv[8]);
|
||||
h->no_answer_count = atoi(agent_no_answer_count);
|
||||
h->max_no_answer = atoi(agent_max_no_answer);
|
||||
h->reject_delay_time = atoi(agent_reject_delay_time);
|
||||
h->busy_delay_time = atoi(agent_busy_delay_time);
|
||||
h->no_answer_delay_time = atoi(agent_no_answer_delay_time);
|
||||
|
||||
|
||||
cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_RECEIVING), h->agent_name);
|
||||
@@ -1895,9 +1920,22 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
|
||||
uint32_t discard_abandoned_after;
|
||||
switch_bool_t abandoned_resume_allowed;
|
||||
agent_callback_t cbt;
|
||||
const char *member_state = NULL;
|
||||
const char *member_abandoned_epoch = NULL;
|
||||
memset(&cbt, 0, sizeof(cbt));
|
||||
|
||||
if (!argv[0] || !(queue = get_queue(argv[0]))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", argv[0]);
|
||||
cbt.queue_name = argv[0];
|
||||
cbt.member_uuid = argv[1];
|
||||
cbt.member_session_uuid = argv[2];
|
||||
cbt.member_cid_number = argv[3];
|
||||
cbt.member_cid_name = argv[4];
|
||||
cbt.member_joined_epoch = argv[5];
|
||||
cbt.member_score = argv[6];
|
||||
member_state = argv[7];
|
||||
member_abandoned_epoch = argv[8];
|
||||
|
||||
if (!cbt.queue_name || !(queue = get_queue(cbt.queue_name))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", cbt.queue_name);
|
||||
goto end;
|
||||
} else {
|
||||
queue_name = strdup(queue->name);
|
||||
@@ -1915,21 +1953,27 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
|
||||
queue_rwunlock(queue);
|
||||
}
|
||||
|
||||
if (!strcasecmp(argv[6], cc_member_state2str(CC_MEMBER_STATE_ABANDONED))) {
|
||||
long abandoned_epoch = atol(argv[7]);
|
||||
/* Checking for cleanup Abandonded calls from the db */
|
||||
if (!strcasecmp(member_state, cc_member_state2str(CC_MEMBER_STATE_ABANDONED))) {
|
||||
long abandoned_epoch = atol(member_abandoned_epoch);
|
||||
if (abandoned_epoch == 0) {
|
||||
abandoned_epoch = atol(argv[4]);
|
||||
abandoned_epoch = atol(cbt.member_joined_epoch);
|
||||
}
|
||||
/* Once we pass a certain point, we want to get rid of the abandoned call */
|
||||
if (abandoned_epoch + discard_abandoned_after < (long) switch_epoch_time_now(NULL)) {
|
||||
sql = switch_mprintf("DELETE FROM members WHERE system = 'single_box' AND uuid = '%q' AND (abandoned_epoch = '%ld' OR joined_epoch = '%q')", argv[1], abandoned_epoch, argv[4]);
|
||||
sql = switch_mprintf("DELETE FROM members WHERE system = 'single_box' AND uuid = '%q' AND (abandoned_epoch = '%ld' OR joined_epoch = '%q')", cbt.member_uuid, abandoned_epoch, cbt.member_joined_epoch);
|
||||
cc_execute_sql(NULL, sql, NULL);
|
||||
switch_safe_free(sql);
|
||||
}
|
||||
/* Skip this member */
|
||||
goto end;
|
||||
}
|
||||
memset(&cbt, 0, sizeof(cbt));
|
||||
|
||||
/* Check if member is in the queue waiting */
|
||||
if (zstr(cbt.member_session_uuid)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Member %s <%s> in Queue %s have no session uuid, skip this member\n", cbt.member_cid_name, cbt.member_cid_number, cbt.queue_name);
|
||||
}
|
||||
|
||||
cbt.tier = 0;
|
||||
cbt.tier_agent_available = 0;
|
||||
|
||||
@@ -1938,11 +1982,6 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
|
||||
cbt.tier_rule_wait_multiply_level = tier_rule_wait_multiply_level;
|
||||
cbt.tier_rule_no_agent_no_wait = tier_rule_no_agent_no_wait;
|
||||
|
||||
cbt.uuid = argv[1];
|
||||
cbt.caller_number = argv[2];
|
||||
cbt.caller_name = argv[3];
|
||||
cbt.joined_epoch = argv[4];
|
||||
cbt.queue_name = argv[0];
|
||||
cbt.strategy = queue_strategy;
|
||||
cbt.record_template = queue_record_template;
|
||||
cbt.agent_found = SWITCH_FALSE;
|
||||
@@ -1955,7 +1994,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
|
||||
sql_order_by = switch_mprintf("level, agents.calls_answered, position");
|
||||
} else if (!strcasecmp(queue_strategy, "ring-all")) {
|
||||
sql = switch_mprintf("UPDATE members SET state = '%q' WHERE state = '%q' AND uuid = '%q' AND system = 'single_box'",
|
||||
cc_member_state2str(CC_MEMBER_STATE_TRYING), cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt.uuid);
|
||||
cc_member_state2str(CC_MEMBER_STATE_TRYING), cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt.member_uuid);
|
||||
cc_execute_sql(NULL, sql, NULL);
|
||||
switch_safe_free(sql);
|
||||
sql_order_by = switch_mprintf("level, position");
|
||||
@@ -1980,8 +2019,8 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
|
||||
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 */
|
||||
if (!argv[0] || !(queue = get_queue(argv[0]))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", argv[0]);
|
||||
if (!cbt.queue_name || !(queue = get_queue(cbt.queue_name))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", cbt.queue_name);
|
||||
goto end;
|
||||
} else {
|
||||
queue->last_agent_exist_check = switch_epoch_time_now(NULL);
|
||||
@@ -2023,7 +2062,7 @@ void *SWITCH_THREAD_FUNC cc_agent_dispatch_thread_run(switch_thread_t *thread, v
|
||||
|
||||
while (globals.running == 1) {
|
||||
char *sql = NULL;
|
||||
sql = switch_mprintf("SELECT queue,uuid,caller_number,caller_name,joined_epoch,(%ld-joined_epoch)+base_score+skill_score AS score, state, abandoned_epoch FROM members"
|
||||
sql = switch_mprintf("SELECT queue,uuid,session_uuid,cid_number,cid_name,joined_epoch,(%ld-joined_epoch)+base_score+skill_score AS score, state, abandoned_epoch FROM members"
|
||||
" WHERE state = '%q' OR state = '%q' OR (serving_agent = 'ring-all' AND state = '%q') ORDER BY score DESC",
|
||||
(long) switch_epoch_time_now(NULL),
|
||||
cc_member_state2str(CC_MEMBER_STATE_WAITING), cc_member_state2str(CC_MEMBER_STATE_ABANDONED), cc_member_state2str(CC_MEMBER_STATE_TRYING));
|
||||
@@ -2071,8 +2110,9 @@ void cc_agent_dispatch_thread_start(void)
|
||||
}
|
||||
|
||||
struct member_thread_helper {
|
||||
const char *member_uuid;
|
||||
const char *queue_name;
|
||||
const char *member_uuid;
|
||||
const char *member_session_uuid;
|
||||
switch_time_t t_member_called;
|
||||
cc_member_cancel_reason_t member_cancel_reason;
|
||||
|
||||
@@ -2083,7 +2123,7 @@ struct member_thread_helper {
|
||||
void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj)
|
||||
{
|
||||
struct member_thread_helper *m = (struct member_thread_helper *) obj;
|
||||
switch_core_session_t *member_session = switch_core_session_locate(m->member_uuid);
|
||||
switch_core_session_t *member_session = switch_core_session_locate(m->member_session_uuid);
|
||||
switch_channel_t *member_channel = NULL;
|
||||
|
||||
switch_mutex_lock(globals.mutex);
|
||||
@@ -2148,8 +2188,8 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj
|
||||
}
|
||||
|
||||
struct moh_dtmf_helper {
|
||||
const char *queue_name;
|
||||
char dtmf;
|
||||
const char *queue_name;
|
||||
char dtmf;
|
||||
};
|
||||
|
||||
static switch_status_t moh_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen) {
|
||||
@@ -2186,7 +2226,7 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
switch_core_session_t *member_session = session;
|
||||
switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
|
||||
char *sql = NULL;
|
||||
char *member_uuid = switch_core_session_get_uuid(member_session);
|
||||
char *member_session_uuid = switch_core_session_get_uuid(member_session);
|
||||
struct member_thread_helper *h = NULL;
|
||||
switch_thread_t *thread;
|
||||
switch_threadattr_t *thd_attr = NULL;
|
||||
@@ -2201,6 +2241,8 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
switch_time_t t_member_called = switch_epoch_time_now(NULL);
|
||||
long abandoned_epoch = 0;
|
||||
const char *agent_uuid = NULL;
|
||||
switch_uuid_t smember_uuid;
|
||||
char member_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1] = "";
|
||||
|
||||
if (!zstr(data)) {
|
||||
mydata = switch_core_session_strdup(member_session, data);
|
||||
@@ -2231,13 +2273,29 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
char res[256];
|
||||
|
||||
/* Check to see if agent already exist */
|
||||
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE queue = '%q' AND caller_number = '%q' AND state = '%q' ORDER BY abandoned_epoch DESC",
|
||||
sql = switch_mprintf("SELECT uuid FROM members WHERE queue = '%q' AND cid_number = '%q' AND state = '%q' ORDER BY abandoned_epoch DESC",
|
||||
queue_name, switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")), cc_member_state2str(CC_MEMBER_STATE_ABANDONED));
|
||||
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
|
||||
switch_safe_free(sql);
|
||||
abandoned_epoch = atol(res);
|
||||
strncpy(member_uuid, res, sizeof(member_uuid));
|
||||
|
||||
if (!zstr(member_uuid)) {
|
||||
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q'", member_uuid);
|
||||
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
|
||||
switch_safe_free(sql);
|
||||
abandoned_epoch = atol(res);
|
||||
}
|
||||
}
|
||||
|
||||
/* If no existing uuid is restored, let create a new one */
|
||||
if (abandoned_epoch == 0) {
|
||||
switch_uuid_get(&smember_uuid);
|
||||
switch_uuid_format(member_uuid, &smember_uuid);
|
||||
}
|
||||
|
||||
switch_channel_set_variable(member_channel, "cc_side", "member");
|
||||
switch_channel_set_variable(member_channel, "cc_member_uuid", member_uuid);
|
||||
|
||||
/* Add manually imported score */
|
||||
if (cc_base_score) {
|
||||
cc_base_score_int += atoi(cc_base_score);
|
||||
@@ -2252,9 +2310,10 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
switch_channel_event_set_data(member_channel, event);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-%s", (abandoned_epoch==0?"start":"resume"));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-Session-UUID", member_session_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
/* for xml_cdr needs */
|
||||
@@ -2264,10 +2323,11 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
if (abandoned_epoch == 0) {
|
||||
/* Add the caller to the member queue */
|
||||
sql = switch_mprintf("INSERT INTO members"
|
||||
" (queue,system,uuid,system_epoch,joined_epoch,base_score,skill_score,caller_number,caller_name,serving_agent,serving_system,state)"
|
||||
" VALUES('%q','single_box','%q','%q','%ld','%d','%d','%q','%q','%q','','%q')",
|
||||
" (queue,system,uuid,session_uuid,system_epoch,joined_epoch,base_score,skill_score,cid_number,cid_name,serving_agent,serving_system,state)"
|
||||
" VALUES('%q','single_box','%q','%q','%q','%ld','%d','%d','%q','%q','%q','','%q')",
|
||||
queue_name,
|
||||
member_uuid,
|
||||
member_session_uuid,
|
||||
start_epoch,
|
||||
(long) switch_epoch_time_now(NULL),
|
||||
cc_base_score_int,
|
||||
@@ -2281,18 +2341,20 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
} else {
|
||||
char res[256];
|
||||
/* Update abandoned member */
|
||||
sql = switch_mprintf("UPDATE members SET uuid = '%q', state = '%q', rejoined_epoch = '%ld' WHERE caller_number = '%q' AND abandoned_epoch = '%ld' AND state = '%q' AND queue = '%q'",
|
||||
member_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), (long) switch_epoch_time_now(NULL), switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")), abandoned_epoch, cc_member_state2str(CC_MEMBER_STATE_ABANDONED), queue_name);
|
||||
sql = switch_mprintf("UPDATE members SET session_uuid = '%q', state = '%q', rejoined_epoch = '%ld' WHERE uuid = '%q' AND state = '%q'",
|
||||
member_session_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), (long) switch_epoch_time_now(NULL), member_uuid, cc_member_state2str(CC_MEMBER_STATE_ABANDONED));
|
||||
cc_execute_sql(queue, sql, NULL);
|
||||
switch_safe_free(sql);
|
||||
|
||||
/* Confirm we took that member in */
|
||||
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q' AND state = '%q' AND queue = '%q'", member_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_session, member_session_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), queue_name);
|
||||
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
|
||||
switch_safe_free(sql);
|
||||
|
||||
if (atol(res) == 0) {
|
||||
/* Failed to get the member !!! */
|
||||
/* TODO Loop back to just create a uuid and add the member as a new member */
|
||||
/* TODO ERROR MSG */
|
||||
queue_rwunlock(queue);
|
||||
goto end;
|
||||
}
|
||||
@@ -2308,6 +2370,7 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
|
||||
h->pool = pool;
|
||||
h->member_uuid = switch_core_strdup(h->pool, member_uuid);
|
||||
h->member_session_uuid = switch_core_strdup(h->pool, member_session_uuid);
|
||||
h->queue_name = switch_core_strdup(h->pool, queue_name);
|
||||
h->t_member_called = t_member_called;
|
||||
h->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NONE;
|
||||
@@ -2374,7 +2437,7 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
/* Canceled for some reason */
|
||||
if (!switch_channel_up(member_channel) || h->member_cancel_reason != CC_MEMBER_CANCEL_REASON_NONE) {
|
||||
/* Update member state */
|
||||
sql = switch_mprintf("UPDATE members SET state = '%q', uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
|
||||
sql = switch_mprintf("UPDATE members SET state = '%q', session_uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
|
||||
cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), member_uuid);
|
||||
cc_execute_sql(NULL, sql, NULL);
|
||||
switch_safe_free(sql);
|
||||
@@ -2387,13 +2450,14 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
switch_channel_event_set_data(member_channel, event);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end");
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Joined-Time", "%ld", (long) t_member_called);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Cancel");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cancel-Reason", cc_member_cancel_reason2str(h->member_cancel_reason));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", member_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-Session-UUID", member_session_uuid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,6 +116,59 @@ static switch_status_t select_url(const char *user,
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define SAY_STRING_SYNTAX "<module_name>[.<ext>] <lang>[.<ext>] <say_type> <say_method> [<say_gender>] <text>"
|
||||
SWITCH_STANDARD_API(say_string_function)
|
||||
{
|
||||
char *argv[6] = { 0 };
|
||||
int argc;
|
||||
char *lbuf = NULL, *string = NULL;
|
||||
int err = 1, par = 0;
|
||||
char *p, *ext = "wav";
|
||||
|
||||
if (cmd) {
|
||||
lbuf = strdup(cmd);
|
||||
}
|
||||
|
||||
if (lbuf && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) && (argc == 5 || argc == 6)) {
|
||||
|
||||
if ((p = strchr(argv[0], '.'))) {
|
||||
*p++ = '\0';
|
||||
ext = p;
|
||||
par++;
|
||||
}
|
||||
|
||||
if (!par && (p = strchr(argv[1], '.'))) {
|
||||
*p++ = '\0';
|
||||
ext = p;
|
||||
}
|
||||
switch_ivr_say_string(session,
|
||||
argv[1],
|
||||
ext,
|
||||
(argc == 5) ? argv[4] : argv[5],
|
||||
argv[0],
|
||||
argv[2],
|
||||
argv[3],
|
||||
(argc == 6) ? argv[4] : NULL ,
|
||||
&string);
|
||||
if (string) {
|
||||
stream->write_function(stream, "%s", string);
|
||||
free(string);
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (err) {
|
||||
stream->write_function(stream, "-ERR Usage: %s\n", SAY_STRING_SYNTAX);
|
||||
}
|
||||
|
||||
free(lbuf);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
|
||||
SWITCH_STANDARD_API(reg_url_function)
|
||||
{
|
||||
char *data;
|
||||
@@ -276,6 +329,7 @@ SWITCH_STANDARD_API(nat_map_function)
|
||||
switch_port_t external_port = 0;
|
||||
char *tmp = NULL;
|
||||
switch_bool_t sticky = SWITCH_FALSE;
|
||||
switch_bool_t mapping = SWITCH_TRUE;
|
||||
|
||||
if (!cmd) {
|
||||
goto usage;
|
||||
@@ -310,6 +364,24 @@ SWITCH_STANDARD_API(nat_map_function)
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
goto usage;
|
||||
}
|
||||
|
||||
if (argv[0] && switch_stristr("mapping", argv[0])) {
|
||||
if (argv[1] && switch_stristr("enable", argv[1])) {
|
||||
mapping = SWITCH_TRUE;
|
||||
} else if (argv[1] && switch_stristr("disable", argv[1])) {
|
||||
mapping = SWITCH_FALSE;
|
||||
}
|
||||
|
||||
switch_nat_set_mapping(mapping);
|
||||
tmp = switch_nat_status();
|
||||
stream->write_function(stream, tmp);
|
||||
switch_safe_free(tmp);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if (argc < 3) {
|
||||
goto error;
|
||||
}
|
||||
@@ -342,7 +414,7 @@ SWITCH_STANDARD_API(nat_map_function)
|
||||
goto ok;
|
||||
|
||||
usage:
|
||||
stream->write_function(stream, "USAGE: nat_map [status|reinit|republish] | [add|del] <port> [tcp|udp] [sticky]");
|
||||
stream->write_function(stream, "USAGE: nat_map [status|reinit|republish] | [add|del] <port> [tcp|udp] [sticky] | [mapping] <enable|disable>");
|
||||
|
||||
ok:
|
||||
|
||||
@@ -4843,6 +4915,87 @@ end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#define LIMIT_SYNTAX "<uuid> <backend> <realm> <resource> [<max>[/interval]] [number [dialplan [context]]]"
|
||||
SWITCH_STANDARD_API(uuid_limit_function)
|
||||
{
|
||||
int argc = 0;
|
||||
char *argv[8] = { 0 };
|
||||
char *mydata = NULL;
|
||||
char *realm = NULL;
|
||||
char *resource = NULL;
|
||||
char *xfer_exten = NULL;
|
||||
int max = -1;
|
||||
int interval = 0;
|
||||
switch_core_session_t *sess = NULL;
|
||||
switch_status_t res = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
if (!zstr(cmd)) {
|
||||
mydata = strdup(cmd);
|
||||
switch_assert(mydata);
|
||||
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
}
|
||||
|
||||
if (argc < 4) {
|
||||
stream->write_function(stream, "USAGE: uuid_limit %s\n", LIMIT_SYNTAX);
|
||||
goto end;
|
||||
}
|
||||
|
||||
realm = argv[2];
|
||||
resource = argv[3];
|
||||
|
||||
/* If max is omitted or negative, only act as a counter and skip maximum checks */
|
||||
if (argc > 4) {
|
||||
if (argv[4][0] == '-') {
|
||||
max = -1;
|
||||
} else {
|
||||
char *szinterval = NULL;
|
||||
if ((szinterval = strchr(argv[4], '/'))) {
|
||||
*szinterval++ = '\0';
|
||||
interval = atoi(szinterval);
|
||||
}
|
||||
|
||||
max = atoi(argv[4]);
|
||||
|
||||
if (max < 0) {
|
||||
max = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > 5) {
|
||||
xfer_exten = argv[5];
|
||||
} else {
|
||||
xfer_exten = LIMIT_DEF_XFER_EXTEN;
|
||||
}
|
||||
|
||||
sess = switch_core_session_locate(argv[0]);
|
||||
if (!sess) {
|
||||
stream->write_function(stream, "-ERR did not find a session with uuid %s\n", argv[0]);
|
||||
goto end;
|
||||
}
|
||||
|
||||
res = switch_limit_incr(argv[1], sess, realm, resource, max, interval);
|
||||
|
||||
if (res != SWITCH_STATUS_SUCCESS) {
|
||||
/* Limit exceeded */
|
||||
if (*xfer_exten == '!') {
|
||||
switch_channel_t *channel = switch_core_session_get_channel(sess);
|
||||
switch_channel_hangup(channel, switch_channel_str2cause(xfer_exten + 1));
|
||||
} else {
|
||||
switch_ivr_session_transfer(sess, xfer_exten, argv[6], argv[7]);
|
||||
}
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(sess);
|
||||
|
||||
stream->write_function(stream, "+OK");
|
||||
|
||||
end:
|
||||
switch_safe_free(mydata);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#define LIMIT_RELEASE_SYNTAX "<uuid> <backend> [realm] [resource]"
|
||||
SWITCH_STANDARD_API(uuid_limit_release_function)
|
||||
{
|
||||
@@ -5024,6 +5177,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
||||
SWITCH_ADD_API(commands_api_interface, "reload", "Reload Module", reload_function, UNLOAD_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "reloadxml", "Reload XML", reload_xml_function, "");
|
||||
SWITCH_ADD_API(commands_api_interface, "replace", "replace a string", replace_function, "<data>|<string1>|<string2>");
|
||||
SWITCH_ADD_API(commands_api_interface, "say_string", "", say_string_function, SAY_STRING_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "sched_api", "Schedule an api command", sched_api_function, SCHED_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "sched_broadcast", "Schedule a broadcast event to a running call", sched_broadcast_function,
|
||||
SCHED_BROADCAST_SYNTAX);
|
||||
@@ -5063,6 +5217,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "uuid_getvar", uuid_getvar_function, GETVAR_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_kill", "Kill Channel", kill_function, KILL_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_limit", "Increase limit resource", uuid_limit_function, LIMIT_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_limit_release", "Release limit resource", uuid_limit_release_function, LIMIT_RELEASE_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_loglevel", "set loglevel on session", uuid_loglevel, UUID_LOGLEVEL_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_media", "media", uuid_media_function, MEDIA_SYNTAX);
|
||||
@@ -5181,6 +5336,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
||||
switch_console_set_complete("add uuid_hold ::console::list_uuid");
|
||||
switch_console_set_complete("add uuid_jitterbuffer ::console::list_uuid");
|
||||
switch_console_set_complete("add uuid_kill ::console::list_uuid");
|
||||
switch_console_set_complete("add uuid_limit ::console::list_uuid");
|
||||
switch_console_set_complete("add uuid_limit_release ::console::list_uuid");
|
||||
switch_console_set_complete("add uuid_loglevel ::console::list_uuid console");
|
||||
switch_console_set_complete("add uuid_loglevel ::console::list_uuid alert");
|
||||
|
||||
@@ -155,7 +155,8 @@ typedef enum {
|
||||
CFLAG_WAIT_MOD = (1 << 7),
|
||||
CFLAG_VID_FLOOR = (1 << 8),
|
||||
CFLAG_WASTE_BANDWIDTH = (1 << 9),
|
||||
CFLAG_OUTCALL = (1 << 10)
|
||||
CFLAG_OUTCALL = (1 << 10),
|
||||
CFLAG_INHASH = (1 << 11)
|
||||
} conf_flag_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -667,7 +668,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
|
||||
lock_member(member);
|
||||
switch_mutex_lock(conference->member_mutex);
|
||||
|
||||
switch_clear_flag(conference, CFLAG_DESTRUCT);
|
||||
|
||||
member->join_time = switch_epoch_time_now(NULL);
|
||||
member->conference = conference;
|
||||
member->next = conference->members;
|
||||
@@ -1491,29 +1492,30 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_test_flag(conference, CFLAG_DESTRUCT)) {
|
||||
switch_core_timer_destroy(&timer);
|
||||
switch_mutex_lock(globals.hash_mutex);
|
||||
|
||||
switch_core_timer_destroy(&timer);
|
||||
switch_mutex_lock(globals.hash_mutex);
|
||||
if (switch_test_flag(conference, CFLAG_INHASH)) {
|
||||
switch_core_hash_delete(globals.conference_hash, conference->name);
|
||||
switch_mutex_unlock(globals.hash_mutex);
|
||||
}
|
||||
switch_mutex_unlock(globals.hash_mutex);
|
||||
|
||||
/* Wait till everybody is out */
|
||||
switch_clear_flag_locked(conference, CFLAG_RUNNING);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Lock ON\n");
|
||||
switch_thread_rwlock_wrlock(conference->rwlock);
|
||||
switch_thread_rwlock_unlock(conference->rwlock);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Lock OFF\n");
|
||||
/* Wait till everybody is out */
|
||||
switch_clear_flag_locked(conference, CFLAG_RUNNING);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Lock ON\n");
|
||||
switch_thread_rwlock_wrlock(conference->rwlock);
|
||||
switch_thread_rwlock_unlock(conference->rwlock);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Lock OFF\n");
|
||||
|
||||
if (conference->sh) {
|
||||
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
|
||||
switch_core_speech_close(&conference->lsh, &flags);
|
||||
conference->sh = NULL;
|
||||
}
|
||||
if (conference->sh) {
|
||||
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
|
||||
switch_core_speech_close(&conference->lsh, &flags);
|
||||
conference->sh = NULL;
|
||||
}
|
||||
|
||||
if (conference->pool) {
|
||||
switch_memory_pool_t *pool = conference->pool;
|
||||
switch_core_destroy_memory_pool(&pool);
|
||||
}
|
||||
if (conference->pool) {
|
||||
switch_memory_pool_t *pool = conference->pool;
|
||||
switch_core_destroy_memory_pool(&pool);
|
||||
}
|
||||
|
||||
switch_mutex_lock(globals.hash_mutex);
|
||||
@@ -2557,10 +2559,6 @@ static void conference_loop_output(conference_member_t *member)
|
||||
|
||||
write_frame.codec = &member->write_codec;
|
||||
|
||||
if (!switch_test_flag(member->conference, CFLAG_ANSWERED)) {
|
||||
switch_channel_answer(channel);
|
||||
}
|
||||
|
||||
if (!restarting) {
|
||||
/* Start the input thread */
|
||||
launch_conference_loop_input(member, switch_core_session_get_pool(member->session));
|
||||
@@ -2607,8 +2605,24 @@ static void conference_loop_output(conference_member_t *member)
|
||||
}
|
||||
switch_safe_free(cpstr);
|
||||
}
|
||||
|
||||
do {
|
||||
switch_ivr_sleep(member->session, 500, SWITCH_TRUE, NULL);
|
||||
} while(switch_channel_up(channel) && member->conference->originating);
|
||||
|
||||
if (!switch_channel_ready(channel)) {
|
||||
member->conference->cancel_cause = SWITCH_CAUSE_ORIGINATOR_CANCEL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
conference_member_play_file(member, "tone_stream://%(500,0,640)", 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!switch_test_flag(member->conference, CFLAG_ANSWERED)) {
|
||||
switch_channel_answer(channel);
|
||||
}
|
||||
|
||||
if (restarting) {
|
||||
switch_channel_clear_app_flag(channel, CF_APP_TAGGED);
|
||||
@@ -2786,8 +2800,9 @@ static void conference_loop_output(conference_member_t *member)
|
||||
switch_cond_next();
|
||||
}
|
||||
|
||||
} /* Rinse ... Repeat */
|
||||
} /* Rinse ... Repeat */
|
||||
|
||||
end:
|
||||
|
||||
switch_clear_flag_locked(member, MFLAG_RUNNING);
|
||||
switch_core_timer_destroy(&timer);
|
||||
@@ -2821,6 +2836,9 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
|
||||
uint32_t rlen;
|
||||
switch_size_t data_buf_len;
|
||||
switch_event_t *event;
|
||||
int no_data = 0;
|
||||
int lead_in = 20;
|
||||
switch_size_t len = 0;
|
||||
|
||||
data_buf_len = samples * sizeof(int16_t);
|
||||
|
||||
@@ -2908,9 +2926,15 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
|
||||
while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(conference, CFLAG_RUNNING) && conference->count) {
|
||||
switch_size_t len = 0;
|
||||
|
||||
len = 0;
|
||||
|
||||
if (lead_in) {
|
||||
lead_in--;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer);
|
||||
|
||||
if (switch_test_flag(member, MFLAG_FLUSH_BUFFER)) {
|
||||
@@ -2923,36 +2947,64 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
|
||||
switch_clear_flag_locked(member, MFLAG_FLUSH_BUFFER);
|
||||
}
|
||||
|
||||
again:
|
||||
|
||||
if (switch_test_flag((&fh), SWITCH_FILE_PAUSE)) {
|
||||
switch_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
|
||||
} else {
|
||||
if (mux_used) {
|
||||
/* Flush the output buffer and write all the data (presumably muxed) to the file */
|
||||
switch_mutex_lock(member->audio_out_mutex);
|
||||
low_count = 0;
|
||||
|
||||
if ((rlen = (uint32_t) switch_buffer_read(member->mux_buffer, data_buf, data_buf_len))) {
|
||||
len = (switch_size_t) rlen / sizeof(int16_t);
|
||||
}
|
||||
switch_mutex_unlock(member->audio_out_mutex);
|
||||
}
|
||||
|
||||
if (len < (switch_size_t) samples) {
|
||||
memset(data_buf + (len * sizeof(int16_t)), 255, ((switch_size_t) samples - len) * sizeof(int16_t));
|
||||
len = (switch_size_t) samples;
|
||||
}
|
||||
|
||||
if (!len || switch_core_file_write(&fh, data_buf, &len) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Failed\n");
|
||||
switch_clear_flag_locked(member, MFLAG_RUNNING);
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
|
||||
if (mux_used >= data_buf_len) {
|
||||
/* Flush the output buffer and write all the data (presumably muxed) to the file */
|
||||
switch_mutex_lock(member->audio_out_mutex);
|
||||
low_count = 0;
|
||||
|
||||
if ((rlen = (uint32_t) switch_buffer_read(member->mux_buffer, data_buf, data_buf_len))) {
|
||||
len = (switch_size_t) rlen / sizeof(int16_t);
|
||||
no_data = 0;
|
||||
}
|
||||
switch_mutex_unlock(member->audio_out_mutex);
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer);
|
||||
|
||||
if (mux_used >= data_buf_len) {
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (++no_data < 2) {
|
||||
goto loop;
|
||||
}
|
||||
|
||||
memset(data_buf, 255, (switch_size_t) data_buf_len);
|
||||
len = (switch_size_t) samples;
|
||||
}
|
||||
|
||||
if (!len || switch_core_file_write(&fh, data_buf, &len) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Failed\n");
|
||||
switch_clear_flag_locked(member, MFLAG_RUNNING);
|
||||
}
|
||||
|
||||
loop:
|
||||
|
||||
switch_core_timer_next(&timer);
|
||||
} /* Rinse ... Repeat */
|
||||
|
||||
end:
|
||||
|
||||
for(;;) {
|
||||
switch_mutex_lock(member->audio_out_mutex);
|
||||
if ((rlen = (uint32_t) switch_buffer_read(member->mux_buffer, data_buf, data_buf_len))) {
|
||||
len = (switch_size_t) rlen / sizeof(int16_t);
|
||||
switch_core_file_write(&fh, data_buf, &len);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
switch_mutex_unlock(member->audio_out_mutex);
|
||||
}
|
||||
|
||||
|
||||
switch_safe_free(data_buf);
|
||||
switch_core_timer_destroy(&timer);
|
||||
conference_del_member(conference, member);
|
||||
@@ -4511,18 +4563,17 @@ static switch_status_t conf_api_sub_bgdial(conference_obj_t *conference, switch_
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
|
||||
{
|
||||
switch_status_t ret_status = SWITCH_STATUS_SUCCESS;
|
||||
char *conf_name = NULL, *profile_name;
|
||||
switch_event_t *params = NULL;
|
||||
conference_obj_t *new_conference = NULL;
|
||||
int locked = 0;
|
||||
switch_core_session_message_t msg = { 0 };
|
||||
|
||||
switch_assert(conference != NULL);
|
||||
switch_assert(stream != NULL);
|
||||
|
||||
|
||||
if (argc > 3 && !zstr(argv[2])) {
|
||||
int x;
|
||||
|
||||
@@ -4539,124 +4590,21 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
|
||||
uint32_t id = atoi(argv[x]);
|
||||
switch_channel_t *channel;
|
||||
switch_event_t *event;
|
||||
switch_xml_t cxml = NULL, cfg = NULL, profiles = NULL;
|
||||
|
||||
char *xdest = NULL;
|
||||
|
||||
if (!id || !(member = conference_member_get(conference, id))) {
|
||||
stream->write_function(stream, "No Member %u in conference %s.\n", id, conference->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
channel = switch_core_session_get_channel(member->session);
|
||||
|
||||
if (!new_conference) {
|
||||
if (!locked) {
|
||||
switch_mutex_lock(globals.setup_mutex);
|
||||
locked = 1;
|
||||
}
|
||||
|
||||
if ((new_conference = conference_find(conf_name))) {
|
||||
if (locked) {
|
||||
switch_mutex_unlock(globals.setup_mutex);
|
||||
locked = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(new_conference = conference_find(conf_name))) {
|
||||
/* build a new conference if it doesn't exist */
|
||||
switch_memory_pool_t *pool = NULL;
|
||||
conf_xml_cfg_t xml_cfg = { 0 };
|
||||
|
||||
/* Setup a memory pool to use. */
|
||||
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n");
|
||||
switch_thread_rwlock_unlock(member->rwlock);
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS);
|
||||
switch_assert(params);
|
||||
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "conf_name", conf_name);
|
||||
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "profile_name", profile_name);
|
||||
switch_channel_event_set_data(channel, params);
|
||||
|
||||
/* Open the config from the xml registry */
|
||||
if (!(cxml = switch_xml_open_cfg(global_cf_name, &cfg, params))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf_name);
|
||||
switch_thread_rwlock_unlock(member->rwlock);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((profiles = switch_xml_child(cfg, "profiles"))) {
|
||||
xml_cfg.profile = switch_xml_find_child(profiles, "profile", "name", profile_name);
|
||||
}
|
||||
|
||||
/* Create the conference object. */
|
||||
new_conference = conference_new(conf_name, xml_cfg, member->session, pool);
|
||||
|
||||
/* Release the config registry handle */
|
||||
if (cxml) {
|
||||
switch_xml_free(cxml);
|
||||
cxml = NULL;
|
||||
}
|
||||
|
||||
if (!new_conference) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
|
||||
if (pool != NULL) {
|
||||
switch_core_destroy_memory_pool(&pool);
|
||||
}
|
||||
switch_thread_rwlock_unlock(member->rwlock);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (locked) {
|
||||
switch_mutex_unlock(globals.setup_mutex);
|
||||
locked = 0;
|
||||
}
|
||||
|
||||
/* Set the minimum number of members (once you go above it you cannot go below it) */
|
||||
new_conference->min = 1;
|
||||
|
||||
/* Indicate the conference is dynamic */
|
||||
switch_set_flag_locked(new_conference, CFLAG_DYNAMIC);
|
||||
|
||||
switch_mutex_lock(new_conference->mutex);
|
||||
|
||||
/* Start the conference thread for this conference */
|
||||
launch_conference_thread(new_conference);
|
||||
} else {
|
||||
switch_mutex_lock(new_conference->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* move the member from the old conference to the new one */
|
||||
lock_member(member);
|
||||
switch_thread_rwlock_unlock(member->rwlock);
|
||||
|
||||
if (conference != new_conference) {
|
||||
conference_del_member(conference, member);
|
||||
conference_add_member(new_conference, member);
|
||||
|
||||
if (conference->rate != new_conference->rate) {
|
||||
if (setup_media(member, new_conference)) {
|
||||
switch_clear_flag_locked(member, MFLAG_RUNNING);
|
||||
} else {
|
||||
switch_channel_set_app_flag(channel, CF_APP_TAGGED);
|
||||
switch_set_flag_locked(member, MFLAG_RESTART);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch_channel_set_variable(channel, "last_transfered_conference", argv[2]);
|
||||
|
||||
/* Sync the recovery data */
|
||||
msg.from = __FILE__;
|
||||
msg.message_id = SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH;
|
||||
switch_core_session_receive_message(member->session, &msg);
|
||||
|
||||
unlock_member(member);
|
||||
xdest = switch_core_session_sprintf(member->session, "conference:%s@%s", conf_name, profile_name);
|
||||
switch_ivr_session_transfer(member->session, xdest, "inline", NULL);
|
||||
|
||||
switch_channel_set_variable(channel, "last_transfered_conference", conf_name);
|
||||
|
||||
stream->write_function(stream, "OK Member '%d' sent to conference %s.\n", member->id, argv[2]);
|
||||
|
||||
|
||||
/* tell them what happened */
|
||||
if (test_eflag(conference, EFLAG_TRANSFER) &&
|
||||
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
|
||||
@@ -4666,30 +4614,23 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "transfer");
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_conference) {
|
||||
switch_mutex_unlock(new_conference->mutex);
|
||||
switch_thread_rwlock_unlock(member->rwlock);
|
||||
}
|
||||
|
||||
} else {
|
||||
ret_status = SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if (locked) {
|
||||
switch_mutex_unlock(globals.setup_mutex);
|
||||
locked = 0;
|
||||
}
|
||||
|
||||
if (params) {
|
||||
switch_event_destroy(¶ms);
|
||||
}
|
||||
|
||||
switch_safe_free(conf_name);
|
||||
|
||||
return ret_status;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
|
||||
{
|
||||
switch_assert(conference != NULL);
|
||||
@@ -5621,6 +5562,7 @@ SWITCH_STANDARD_APP(conference_function)
|
||||
conf_xml_cfg_t xml_cfg = { 0 };
|
||||
switch_event_t *params = NULL;
|
||||
int locked = 0;
|
||||
uint32_t *mid;
|
||||
|
||||
if (!switch_channel_test_app_flag_key("conf_silent", channel, CONF_SILENT_DONE) &&
|
||||
(switch_channel_test_flag(channel, CF_RECOVERED) || switch_true(switch_channel_get_variable(channel, "conference_silent_entry")))) {
|
||||
@@ -5993,8 +5935,17 @@ SWITCH_STANDARD_APP(conference_function)
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
if (!(mid = switch_channel_get_private(channel, "__confmid"))) {
|
||||
mid = switch_core_session_alloc(session, sizeof(*mid));
|
||||
*mid = next_member_id();
|
||||
switch_channel_set_private(channel, "__confmid", mid);
|
||||
}
|
||||
|
||||
switch_channel_set_variable_printf(channel, "conference_member_id", "%u", *mid);
|
||||
|
||||
/* Prepare MUTEXS */
|
||||
member.id = next_member_id();
|
||||
member.id = *mid;
|
||||
switch_mutex_init(&member.flag_mutex, SWITCH_MUTEX_NESTED, member.pool);
|
||||
switch_mutex_init(&member.write_mutex, SWITCH_MUTEX_NESTED, member.pool);
|
||||
switch_mutex_init(&member.read_mutex, SWITCH_MUTEX_NESTED, member.pool);
|
||||
@@ -6219,7 +6170,13 @@ static conference_obj_t *conference_find(char *name)
|
||||
conference_obj_t *conference;
|
||||
|
||||
switch_mutex_lock(globals.hash_mutex);
|
||||
conference = switch_core_hash_find(globals.conference_hash, name);
|
||||
if ((conference = switch_core_hash_find(globals.conference_hash, name))) {
|
||||
if (switch_test_flag(conference, CFLAG_DESTRUCT)) {
|
||||
switch_core_hash_delete(globals.conference_hash, conference->name);
|
||||
switch_clear_flag(conference, CFLAG_INHASH);
|
||||
conference = NULL;
|
||||
}
|
||||
}
|
||||
switch_mutex_unlock(globals.hash_mutex);
|
||||
|
||||
return conference;
|
||||
@@ -6669,7 +6626,9 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
|
||||
switch_mutex_init(&conference->flag_mutex, SWITCH_MUTEX_NESTED, conference->pool);
|
||||
switch_thread_rwlock_create(&conference->rwlock, conference->pool);
|
||||
switch_mutex_init(&conference->member_mutex, SWITCH_MUTEX_NESTED, conference->pool);
|
||||
|
||||
switch_mutex_lock(globals.hash_mutex);
|
||||
switch_set_flag(conference, CFLAG_INHASH);
|
||||
switch_core_hash_insert(globals.conference_hash, conference->name, conference);
|
||||
switch_mutex_unlock(globals.hash_mutex);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
* Neal Horman <neal at wanlink dot com>
|
||||
* Bret McDanel <trixter AT 0xdecafbad dot com>
|
||||
* Luke Dashjr <luke@openmethods.com> (OpenMethods, LLC)
|
||||
* Cesar Cepeda <cesar@auronix.com>
|
||||
*
|
||||
* mod_dptools.c -- Raw Audio File Streaming Application Module
|
||||
*
|
||||
@@ -2077,7 +2078,7 @@ SWITCH_STANDARD_APP(play_and_get_digits_function)
|
||||
prompt_audio_file, bad_input_audio_file, var_name, digit_buffer, sizeof(digit_buffer), digits_regex, digit_timeout);
|
||||
}
|
||||
|
||||
#define SAY_SYNTAX "<module_name> <say_type> <say_method> [<say_gender>] <text>"
|
||||
#define SAY_SYNTAX "<module_name>[:<lang>] <say_type> <say_method> [<say_gender>] <text>"
|
||||
SWITCH_STANDARD_APP(say_function)
|
||||
{
|
||||
char *argv[5] = { 0 };
|
||||
@@ -2093,6 +2094,11 @@ SWITCH_STANDARD_APP(say_function)
|
||||
|
||||
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
|
||||
|
||||
/* Set default langauge according to the <module_name> */
|
||||
if (!strchr(argv[0], ':')) {
|
||||
argv[0] = switch_core_session_sprintf(session, "%s:%s", argv[0], argv[0]);
|
||||
}
|
||||
|
||||
switch_ivr_say(session, (argc == 4) ? argv[3] : argv[4], argv[0], argv[1], argv[2], (argc == 5) ? argv[3] : NULL ,&args);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", SAY_SYNTAX);
|
||||
@@ -2473,6 +2479,11 @@ SWITCH_STANDARD_APP(audio_bridge_function)
|
||||
{
|
||||
switch_channel_t *caller_channel = switch_core_session_get_channel(session);
|
||||
switch_core_session_t *peer_session = NULL;
|
||||
|
||||
const char *transfer_on_fail = NULL;
|
||||
char *tof_data = NULL;
|
||||
char *tof_array[4] = { 0 };
|
||||
int tof_arrayc = 0;
|
||||
const char *continue_on_fail = NULL, *failure_causes = NULL,
|
||||
*v_campon = NULL, *v_campon_retries, *v_campon_sleep, *v_campon_timeout, *v_campon_fallback_exten = NULL;
|
||||
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
|
||||
@@ -2489,8 +2500,14 @@ SWITCH_STANDARD_APP(audio_bridge_function)
|
||||
}
|
||||
|
||||
continue_on_fail = switch_channel_get_variable(caller_channel, "continue_on_fail");
|
||||
failure_causes = switch_channel_get_variable(caller_channel, "failure_causes");
|
||||
|
||||
transfer_on_fail = switch_channel_get_variable(caller_channel, "transfer_on_fail");
|
||||
tof_data = switch_core_session_strdup(session, transfer_on_fail);
|
||||
tof_arrayc = switch_split(tof_data, ' ', tof_array);
|
||||
transfer_on_fail = tof_array[0];
|
||||
|
||||
failure_causes = switch_channel_get_variable(caller_channel, "failure_causes");
|
||||
|
||||
if ((v_campon = switch_channel_get_variable(caller_channel, "campon")) && switch_true(v_campon)) {
|
||||
const char *cid_name = NULL;
|
||||
const char *cid_number = NULL;
|
||||
@@ -2681,6 +2698,57 @@ SWITCH_STANDARD_APP(audio_bridge_function)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (transfer_on_fail || failure_causes) {
|
||||
const char *cause_str;
|
||||
char cause_num[35] = "";
|
||||
|
||||
cause_str = switch_channel_cause2str(cause);
|
||||
switch_snprintf(cause_num, sizeof(cause_num), "%u", cause);
|
||||
|
||||
if ((tof_array[1] == NULL ) || (!strcasecmp(tof_array[1], "auto_cause"))){
|
||||
tof_array[1] = (char *) cause_str;
|
||||
}
|
||||
|
||||
if (failure_causes) {
|
||||
char *lbuf = switch_core_session_strdup(session, failure_causes);
|
||||
char *argv[256] = { 0 };
|
||||
int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
int i, x = 0;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
|
||||
x++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!x) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"Failure causes [%s]: Cause: %s\n", failure_causes, cause_str);
|
||||
|
||||
switch_ivr_session_transfer(session, tof_array[1], tof_array[2], tof_array[3]);
|
||||
}
|
||||
}
|
||||
|
||||
if (transfer_on_fail) {
|
||||
if (switch_true(transfer_on_fail)) {
|
||||
return;
|
||||
} else {
|
||||
char *lbuf = switch_core_session_strdup(session, transfer_on_fail);
|
||||
char *argv[256] = { 0 };
|
||||
int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"Transfer on fail [%s]: Cause: %s\n", transfer_on_fail, cause_str);
|
||||
switch_ivr_session_transfer(session, tof_array[1], tof_array[2], tof_array[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!switch_channel_test_flag(caller_channel, CF_TRANSFER) && switch_channel_get_state(caller_channel) != CS_ROUTING) {
|
||||
switch_channel_hangup(caller_channel, cause);
|
||||
@@ -2789,7 +2857,7 @@ static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session
|
||||
if ((domain = strchr(group, '@'))) {
|
||||
*domain++ = '\0';
|
||||
} else {
|
||||
domain = switch_core_get_variable_pdup("domain", switch_core_session_get_pool(session));
|
||||
domain = switch_core_get_variable_dup("domain");
|
||||
dup_domain = domain;
|
||||
}
|
||||
|
||||
@@ -2890,7 +2958,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
|
||||
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
|
||||
switch_call_cause_t *cancel_cause)
|
||||
{
|
||||
switch_xml_t x_domain = NULL, xml = NULL, x_user = NULL, x_group = NULL, x_param, x_params;
|
||||
switch_xml_t xml = NULL, x_user = NULL, x_param, x_params;
|
||||
char *user = NULL, *domain = NULL, *dup_domain = NULL;
|
||||
const char *dest = NULL;
|
||||
switch_call_cause_t cause = SWITCH_CAUSE_NONE;
|
||||
@@ -2937,48 +3005,12 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
|
||||
var_event = NULL;
|
||||
}
|
||||
|
||||
if (switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, &x_group, params) != SWITCH_STATUS_SUCCESS) {
|
||||
if (switch_xml_locate_user_merged("id", user, domain, NULL, &x_user, params) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n", user, domain);
|
||||
cause = SWITCH_CAUSE_SUBSCRIBER_ABSENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((x_params = switch_xml_child(x_domain, "params"))) {
|
||||
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
|
||||
const char *pvar = switch_xml_attr(x_param, "name");
|
||||
const char *val = switch_xml_attr(x_param, "value");
|
||||
|
||||
if (!strcasecmp(pvar, "dial-string")) {
|
||||
dest = val;
|
||||
} else if (!strncasecmp(pvar, "dial-var-", 9)) {
|
||||
if (!var_event) {
|
||||
switch_event_create(&var_event, SWITCH_EVENT_GENERAL);
|
||||
} else {
|
||||
switch_event_del_header(var_event, pvar + 9);
|
||||
}
|
||||
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, pvar + 9, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((x_params = switch_xml_child(x_group, "params"))) {
|
||||
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
|
||||
const char *pvar = switch_xml_attr(x_param, "name");
|
||||
const char *val = switch_xml_attr(x_param, "value");
|
||||
|
||||
if (!strcasecmp(pvar, "dial-string")) {
|
||||
dest = val;
|
||||
} else if (!strncasecmp(pvar, "dial-var-", 9)) {
|
||||
if (!var_event) {
|
||||
switch_event_create(&var_event, SWITCH_EVENT_GENERAL);
|
||||
} else {
|
||||
switch_event_del_header(var_event, pvar + 9);
|
||||
}
|
||||
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, pvar + 9, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((x_params = switch_xml_child(x_user, "params"))) {
|
||||
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
|
||||
const char *pvar = switch_xml_attr(x_param, "name");
|
||||
@@ -2996,8 +3028,9 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
|
||||
}
|
||||
}
|
||||
}
|
||||
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", user);
|
||||
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
|
||||
|
||||
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", user);
|
||||
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
|
||||
|
||||
if (!dest) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No dial-string available, please check your user directory.\n");
|
||||
@@ -3090,14 +3123,6 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
|
||||
}
|
||||
|
||||
if (new_channel && xml) {
|
||||
if ((x_params = switch_xml_child(x_domain, "variables"))) {
|
||||
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
|
||||
const char *pvar = switch_xml_attr(x_param, "name");
|
||||
const char *val = switch_xml_attr(x_param, "value");
|
||||
switch_channel_set_variable(new_channel, pvar, val);
|
||||
}
|
||||
}
|
||||
|
||||
if ((x_params = switch_xml_child(x_user, "variables"))) {
|
||||
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
|
||||
const char *pvar = switch_xml_attr(x_param, "name");
|
||||
@@ -3463,6 +3488,173 @@ SWITCH_STANDARD_APP(limit_hash_execute_function)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* FILE STRING INTERFACE */
|
||||
|
||||
/* for apr_pstrcat */
|
||||
#define DEFAULT_PREBUFFER_SIZE 1024 * 64
|
||||
|
||||
struct file_string_source;
|
||||
|
||||
struct file_string_context {
|
||||
char *argv[128];
|
||||
int argc;
|
||||
int index;
|
||||
int samples;
|
||||
switch_file_handle_t fh;
|
||||
};
|
||||
|
||||
typedef struct file_string_context file_string_context_t;
|
||||
|
||||
|
||||
static int next_file(switch_file_handle_t *handle)
|
||||
{
|
||||
file_string_context_t *context = handle->private_info;
|
||||
char *file;
|
||||
const char *prefix = handle->prefix;
|
||||
|
||||
top:
|
||||
|
||||
context->index++;
|
||||
|
||||
if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) {
|
||||
switch_core_file_close(&context->fh);
|
||||
}
|
||||
|
||||
if (context->index >= context->argc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (!prefix) {
|
||||
if (!(prefix = switch_core_get_variable_pdup("sound_prefix", handle->memory_pool))) {
|
||||
prefix = SWITCH_GLOBAL_dirs.sounds_dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (!prefix || switch_is_file_path(context->argv[context->index])) {
|
||||
file = context->argv[context->index];
|
||||
} else {
|
||||
file = switch_core_sprintf(handle->memory_pool, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, context->argv[context->index]);
|
||||
}
|
||||
|
||||
if (switch_core_file_open(&context->fh,
|
||||
file, handle->channels, handle->samplerate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
|
||||
goto top;
|
||||
}
|
||||
|
||||
handle->samples = context->fh.samples;
|
||||
handle->samplerate = context->fh.samplerate;
|
||||
handle->channels = context->fh.channels;
|
||||
handle->format = context->fh.format;
|
||||
handle->sections = context->fh.sections;
|
||||
handle->seekable = context->fh.seekable;
|
||||
handle->speed = context->fh.speed;
|
||||
handle->interval = context->fh.interval;
|
||||
|
||||
if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) {
|
||||
switch_set_flag(handle, SWITCH_FILE_NATIVE);
|
||||
} else {
|
||||
switch_clear_flag(handle, SWITCH_FILE_NATIVE);
|
||||
}
|
||||
|
||||
|
||||
if (!switch_test_flag(handle, SWITCH_FILE_NATIVE)) {
|
||||
if (context->index == 0) {
|
||||
context->samples = (handle->samplerate / 1000) * 250;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t file_string_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
|
||||
{
|
||||
file_string_context_t *context = handle->private_info;
|
||||
|
||||
if (samples == 0 && whence == SEEK_SET) {
|
||||
context->index = -1;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!handle->seekable) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File is not seekable\n");
|
||||
return SWITCH_STATUS_NOTIMPL;
|
||||
}
|
||||
|
||||
return switch_core_file_seek(&context->fh, cur_sample, samples, whence);
|
||||
}
|
||||
|
||||
static switch_status_t file_string_file_open(switch_file_handle_t *handle, const char *path)
|
||||
{
|
||||
file_string_context_t *context;
|
||||
char *file_dup;
|
||||
|
||||
if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "This format does not support writing!\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
context = switch_core_alloc(handle->memory_pool, sizeof(*context));
|
||||
|
||||
file_dup = switch_core_strdup(handle->memory_pool, path);
|
||||
context->argc = switch_separate_string(file_dup, '!', context->argv, (sizeof(context->argv) / sizeof(context->argv[0])));
|
||||
context->index = -1;
|
||||
|
||||
handle->private_info = context;
|
||||
|
||||
return next_file(handle) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
static switch_status_t file_string_file_close(switch_file_handle_t *handle)
|
||||
{
|
||||
file_string_context_t *context = handle->private_info;
|
||||
|
||||
switch_core_file_close(&context->fh);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t file_string_file_read(switch_file_handle_t *handle, void *data, size_t *len)
|
||||
{
|
||||
file_string_context_t *context = handle->private_info;
|
||||
switch_status_t status;
|
||||
size_t llen = *len;
|
||||
|
||||
if (context->samples > 0) {
|
||||
if (*len > (size_t) context->samples) {
|
||||
*len = context->samples;
|
||||
}
|
||||
|
||||
context->samples -= *len;
|
||||
memset(data, 255, *len *2);
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
} else {
|
||||
status = switch_core_file_read(&context->fh, data, len);
|
||||
}
|
||||
|
||||
if (status != SWITCH_STATUS_SUCCESS) {
|
||||
if (!next_file(handle)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
*len = llen;
|
||||
status = switch_core_file_read(&context->fh, data, len);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Registration */
|
||||
|
||||
static char *file_string_supported_formats[SWITCH_MAX_CODECS] = { 0 };
|
||||
|
||||
|
||||
/* /FILE STRING INTERFACE */
|
||||
|
||||
|
||||
|
||||
#define SPEAK_DESC "Speak text to a channel via the tts interface"
|
||||
#define DISPLACE_DESC "Displace audio from a file to the channels input"
|
||||
#define SESS_REC_DESC "Starts a background recording of the entire session"
|
||||
@@ -3484,10 +3676,22 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
|
||||
switch_application_interface_t *app_interface;
|
||||
switch_dialplan_interface_t *dp_interface;
|
||||
switch_chat_interface_t *chat_interface;
|
||||
switch_file_interface_t *file_interface;
|
||||
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
file_string_supported_formats[0] = "file_string";
|
||||
|
||||
file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
|
||||
file_interface->interface_name = modname;
|
||||
file_interface->extens = file_string_supported_formats;
|
||||
file_interface->file_open = file_string_file_open;
|
||||
file_interface->file_close = file_string_file_close;
|
||||
file_interface->file_read = file_string_file_read;
|
||||
file_interface->file_seek = file_string_file_seek;
|
||||
|
||||
|
||||
error_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
|
||||
error_endpoint_interface->interface_name = "error";
|
||||
error_endpoint_interface->io_routines = &error_io_routines;
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
# LDNS=ldns-1.6.9
|
||||
# BASE=../../../..
|
||||
|
||||
# LDNS_DIR=$(switch_srcdir)/libs/$(LDNS)
|
||||
# LDNS_BUILDDIR=$(switch_builddir)/libs/$(LDNS)
|
||||
# LDNSLA=$(LDNS_BUILDDIR)/libldns.la
|
||||
|
||||
# include $(BASE)/build/modmake.rules
|
||||
# LOCAL_LIBADD=$(LDNSLA)
|
||||
|
||||
|
||||
BASE=../../../..
|
||||
|
||||
LDNS=ldns-1.6.9
|
||||
LDNS=ldns
|
||||
|
||||
LDNS_DIR=$(switch_srcdir)/libs/$(LDNS)
|
||||
LDNS_BUILDDIR=$(switch_builddir)/libs/$(LDNS)
|
||||
@@ -20,9 +9,6 @@ LDNS_LA=$(LDNS_BUILDDIR)/libldns.la
|
||||
LOCAL_LIBADD=$(LDNS_LA)
|
||||
include $(BASE)/build/modmake.rules
|
||||
|
||||
$(LDNS_DIR)/Makefile.in:
|
||||
$(GETLIB) $(LDNS).tar.gz
|
||||
|
||||
$(LDNS_BUILDDIR)/Makefile: $(LDNS_DIR)/Makefile.in
|
||||
mkdir -p $(LDNS_BUILDDIR)
|
||||
cd $(LDNS_BUILDDIR) && $(DEFAULT_VARS) $(LDNS_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(LDNS_DIR) --disable-gost --without-ssl --disable-sha2
|
||||
@@ -32,3 +18,4 @@ $(LDNS_LA): $(LDNS_BUILDDIR)/Makefile
|
||||
cd $(LDNS_BUILDDIR) && $(MAKE)
|
||||
$(TOUCH_TARGET)
|
||||
|
||||
$(MODNAME).lo: $(LDNS_LA)
|
||||
@@ -0,0 +1,323 @@
|
||||
diff -ru b/ldns/ldns.h a/ldns/ldns.h
|
||||
--- b/ldns/ldns.h 2011-03-24 20:32:30.000000000 -0500
|
||||
+++ a/ldns/ldns.h 2011-03-24 20:29:03.000000000 -0500
|
||||
@@ -148,6 +148,16 @@
|
||||
/** EDNS flags */
|
||||
extern ldns_lookup_table ldns_edns_flags[];
|
||||
|
||||
+
|
||||
+#ifdef USE_WINSOCK
|
||||
+#define SOCK_INVALID INVALID_SOCKET
|
||||
+#define close_socket(_s) if (_s > SOCK_INVALID) {closesocket(_s); _s = SOCK_INVALID;}
|
||||
+#else
|
||||
+#define SOCK_INVALID -1
|
||||
+#define close_socket(_s) if (_s > SOCK_INVALID) {close(_s); _s = SOCK_INVALID;}
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff -ru b/net.c a/net.c
|
||||
--- b/net.c 2011-02-11 10:50:46.000000000 -0600
|
||||
+++ a/net.c 2011-03-24 20:28:15.000000000 -0500
|
||||
@@ -261,12 +261,18 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
+#ifndef WIN32
|
||||
+#include <poll.h>
|
||||
+#endif
|
||||
+
|
||||
/** wait for a socket to become ready */
|
||||
static int
|
||||
ldns_sock_wait(int sockfd, struct timeval timeout, int write)
|
||||
{
|
||||
- fd_set fds;
|
||||
int ret;
|
||||
+
|
||||
+#ifdef WIN32
|
||||
+ fd_set fds;
|
||||
#ifndef S_SPLINT_S
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(FD_SET_T sockfd, &fds);
|
||||
@@ -275,6 +281,26 @@
|
||||
ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
|
||||
else
|
||||
ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
|
||||
+#else
|
||||
+
|
||||
+ struct pollfd pfds[2];
|
||||
+ int x = 0;
|
||||
+
|
||||
+ memset(&pfds[0], 0, sizeof(pfds[0]) * 2);
|
||||
+
|
||||
+ pfds[0].fd = sockfd;
|
||||
+ pfds[0].events = POLLIN|POLLERR;
|
||||
+
|
||||
+ if (write) {
|
||||
+ pfds[0].events |= POLLOUT;
|
||||
+ }
|
||||
+
|
||||
+ ret = poll(pfds, 1, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+
|
||||
if(ret == 0)
|
||||
/* timeout expired */
|
||||
return 0;
|
||||
@@ -299,11 +325,7 @@
|
||||
|
||||
/* wait for an response*/
|
||||
if(!ldns_sock_wait(sockfd, timeout, 0)) {
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(sockfd);
|
||||
-#else
|
||||
- closesocket(sockfd);
|
||||
-#endif
|
||||
+ close_socket(sockfd);
|
||||
return LDNS_STATUS_NETWORK_ERR;
|
||||
}
|
||||
|
||||
@@ -313,11 +335,7 @@
|
||||
ldns_sock_nonblock(sockfd);
|
||||
|
||||
answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(sockfd);
|
||||
-#else
|
||||
- closesocket(sockfd);
|
||||
-#endif
|
||||
+ close_socket(sockfd);
|
||||
|
||||
if (*answer_size == 0) {
|
||||
/* oops */
|
||||
@@ -353,9 +371,10 @@
|
||||
|
||||
if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM,
|
||||
IPPROTO_UDP))
|
||||
- == -1) {
|
||||
+ == SOCK_INVALID) {
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
@@ -366,20 +385,20 @@
|
||||
int sockfd;
|
||||
|
||||
if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM,
|
||||
- IPPROTO_TCP)) == -1) {
|
||||
+ IPPROTO_TCP)) == SOCK_INVALID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* perform nonblocking connect, to be able to wait with select() */
|
||||
ldns_sock_nonblock(sockfd);
|
||||
- if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) {
|
||||
+ if (connect(sockfd, (struct sockaddr*)to, tolen) == SOCK_INVALID) {
|
||||
#ifndef USE_WINSOCK
|
||||
#ifdef EINPROGRESS
|
||||
if(errno != EINPROGRESS) {
|
||||
#else
|
||||
if(1) {
|
||||
#endif
|
||||
- close(sockfd);
|
||||
+ close_socket(sockfd);
|
||||
return 0;
|
||||
}
|
||||
#else /* USE_WINSOCK */
|
||||
@@ -398,11 +417,7 @@
|
||||
socklen_t len = (socklen_t)sizeof(error);
|
||||
|
||||
if(!ldns_sock_wait(sockfd, timeout, 1)) {
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(sockfd);
|
||||
-#else
|
||||
- closesocket(sockfd);
|
||||
-#endif
|
||||
+ close_socket(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -421,7 +436,7 @@
|
||||
continue; /* try again */
|
||||
#endif
|
||||
else if(error != 0) {
|
||||
- close(sockfd);
|
||||
+ close_socket(sockfd);
|
||||
/* error in errno for our user */
|
||||
errno = error;
|
||||
return 0;
|
||||
@@ -645,11 +660,7 @@
|
||||
}
|
||||
|
||||
answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(sockfd);
|
||||
-#else
|
||||
- closesocket(sockfd);
|
||||
-#endif
|
||||
+ close_socket(sockfd);
|
||||
|
||||
if (*answer_size == 0) {
|
||||
/* oops */
|
||||
@@ -782,7 +793,7 @@
|
||||
* @hostname is used */
|
||||
for (ns_i = 0;
|
||||
ns_i < ldns_resolver_nameserver_count(resolver) &&
|
||||
- resolver->_socket == 0;
|
||||
+ resolver->_socket == SOCK_INVALID;
|
||||
ns_i++) {
|
||||
ns = ldns_rdf2native_sockaddr_storage(
|
||||
resolver->_nameservers[ns_i],
|
||||
@@ -792,7 +803,7 @@
|
||||
ldns_resolver_timeout(resolver));
|
||||
}
|
||||
|
||||
- if (resolver->_socket == 0) {
|
||||
+ if (resolver->_socket == SOCK_INVALID) {
|
||||
ldns_pkt_free(query);
|
||||
LDNS_FREE(ns);
|
||||
return LDNS_STATUS_NETWORK_ERR;
|
||||
@@ -807,13 +818,7 @@
|
||||
if (status != LDNS_STATUS_OK) {
|
||||
/* RoRi: to prevent problems on subsequent calls to ldns_axfr_start
|
||||
we have to close the socket here! */
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
-
|
||||
+ close_socket(resolver->_socket);
|
||||
return LDNS_STATUS_CRYPTO_TSIG_ERR;
|
||||
}
|
||||
}
|
||||
@@ -826,12 +831,8 @@
|
||||
if(!query_wire) {
|
||||
ldns_pkt_free(query);
|
||||
LDNS_FREE(ns);
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
+
|
||||
+ close_socket(resolver->_socket);
|
||||
|
||||
return LDNS_STATUS_MEM_ERR;
|
||||
}
|
||||
@@ -843,12 +844,8 @@
|
||||
|
||||
/* RoRi: to prevent problems on subsequent calls to ldns_axfr_start
|
||||
we have to close the socket here! */
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
+
|
||||
+ close_socket(resolver->_socket);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -862,12 +859,8 @@
|
||||
/* RoRi: to prevent problems on subsequent calls to ldns_axfr_start
|
||||
we have to close the socket here! */
|
||||
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
+
|
||||
+ close_socket(resolver->_socket);
|
||||
|
||||
return LDNS_STATUS_NETWORK_ERR;
|
||||
}
|
||||
diff -ru b/resolver.c a/resolver.c
|
||||
--- b/resolver.c 2010-12-14 08:41:38.000000000 -0600
|
||||
+++ a/resolver.c 2011-03-24 20:07:17.000000000 -0500
|
||||
@@ -627,9 +627,7 @@
|
||||
r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
|
||||
r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
|
||||
|
||||
- /* TODO: fd=0 is actually a valid socket (stdin),
|
||||
- replace with -1 */
|
||||
- r->_socket = 0;
|
||||
+ r->_socket = -1;
|
||||
r->_axfr_soa_count = 0;
|
||||
r->_axfr_i = 0;
|
||||
r->_cur_axfr_pkt = NULL;
|
||||
@@ -903,6 +901,8 @@
|
||||
size_t i;
|
||||
|
||||
if (res) {
|
||||
+ close_socket(res->_socket);
|
||||
+
|
||||
if (res->_searchlist) {
|
||||
for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
|
||||
ldns_rdf_deep_free(res->_searchlist[i]);
|
||||
@@ -1198,7 +1198,7 @@
|
||||
ldns_status status;
|
||||
|
||||
/* check if start() has been called */
|
||||
- if (!resolver || resolver->_socket == 0) {
|
||||
+ if (!resolver || resolver->_socket == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1215,12 +1215,9 @@
|
||||
if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
|
||||
resolver->_axfr_soa_count++;
|
||||
if (resolver->_axfr_soa_count >= 2) {
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
+
|
||||
+ close_socket(resolver->_socket);
|
||||
+
|
||||
ldns_pkt_free(resolver->_cur_axfr_pkt);
|
||||
resolver->_cur_axfr_pkt = NULL;
|
||||
}
|
||||
@@ -1243,12 +1240,8 @@
|
||||
/* RoRi: we must now also close the socket, otherwise subsequent uses of the
|
||||
same resolver structure will fail because the link is still open or
|
||||
in an undefined state */
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
+
|
||||
+ close_socket(resolver->_socket);
|
||||
|
||||
return NULL;
|
||||
} else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
|
||||
@@ -1258,12 +1251,8 @@
|
||||
/* RoRi: we must now also close the socket, otherwise subsequent uses of the
|
||||
same resolver structure will fail because the link is still open or
|
||||
in an undefined state */
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
+
|
||||
+ close_socket(resolver->_socket);
|
||||
|
||||
return NULL;
|
||||
} else {
|
||||
@@ -42,7 +42,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\udns""
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\ldns""
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
@@ -106,7 +106,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\udns""
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\ldns""
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
@@ -171,7 +171,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\udns""
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\ldns""
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
@@ -235,7 +235,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\udns""
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\ldns""
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\udns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\ldns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -82,7 +82,7 @@
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\udns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\ldns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -96,7 +96,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\udns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\ldns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -112,7 +112,7 @@
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\udns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\ldns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -128,9 +128,8 @@
|
||||
<ClCompile Include="mod_enum.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\libs\win32\udns\libudns.2010.vcxproj">
|
||||
<Project>{4043fc6a-9a30-4577-8ad5-9b233c9575d8}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
<ProjectReference Include="..\..\..\..\libs\win32\ldns\ldns-lib\ldns-lib.2010.vcxproj">
|
||||
<Project>{23b4d303-79fc-49e0-89e2-2280e7e28940}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
|
||||
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#ifdef _MSC_VER
|
||||
#define ssize_t int
|
||||
#endif
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_enum_load);
|
||||
@@ -141,6 +144,32 @@ static switch_status_t load_config(void)
|
||||
}
|
||||
|
||||
done:
|
||||
#ifdef _MSC_VER
|
||||
if (!globals.server) {
|
||||
HKEY hKey;
|
||||
DWORD data_sz;
|
||||
char* buf;
|
||||
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
|
||||
0, KEY_QUERY_VALUE, &hKey);
|
||||
|
||||
if (hKey) {
|
||||
RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, NULL, &data_sz);
|
||||
if (data_sz) {
|
||||
buf = (char*)malloc(data_sz + 1);
|
||||
|
||||
RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, (LPBYTE)buf, &data_sz);
|
||||
RegCloseKey(hKey);
|
||||
|
||||
if(buf[data_sz - 1] != 0) {
|
||||
buf[data_sz] = 0;
|
||||
}
|
||||
globals.server = buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (xml) {
|
||||
switch_xml_free(xml);
|
||||
@@ -380,9 +409,7 @@ switch_status_t ldns_lookup(const char *number, const char *root, const char *se
|
||||
goto end;
|
||||
}
|
||||
|
||||
domain = ldns_dname_new_frm_str(name);
|
||||
|
||||
if (!domain) {
|
||||
if (!(domain = ldns_dname_new_frm_str(name))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -403,12 +430,6 @@ switch_status_t ldns_lookup(const char *number, const char *root, const char *se
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* use the resolver to send a query for the naptr
|
||||
* records of the domain given on the command line
|
||||
*/
|
||||
|
||||
|
||||
|
||||
if ((p = ldns_resolver_query(res,
|
||||
domain,
|
||||
LDNS_RR_TYPE_NAPTR,
|
||||
@@ -417,7 +438,7 @@ switch_status_t ldns_lookup(const char *number, const char *root, const char *se
|
||||
/* retrieve the NAPTR records from the answer section of that
|
||||
* packet
|
||||
*/
|
||||
|
||||
|
||||
if ((naptr = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NAPTR, LDNS_SECTION_ANSWER))) {
|
||||
size_t i;
|
||||
|
||||
@@ -472,11 +493,10 @@ static switch_status_t enum_lookup(char *root, char *in, enum_record_t **results
|
||||
root = globals.root;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
if (!(server = switch_core_get_variable("enum-server"))) {
|
||||
server = globals.server;
|
||||
}
|
||||
#endif
|
||||
|
||||
ldns_lookup(mnum, root, server, results);
|
||||
|
||||
@@ -775,8 +795,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_enum_shutdown)
|
||||
}
|
||||
|
||||
switch_safe_free(globals.root);
|
||||
switch_safe_free(globals.server);
|
||||
switch_safe_free(globals.isn_root);
|
||||
|
||||
|
||||
return SWITCH_STATUS_UNLOAD;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,6 +153,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lcr_load);
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_lcr_shutdown);
|
||||
SWITCH_MODULE_DEFINITION(mod_lcr, mod_lcr_load, mod_lcr_shutdown, NULL);
|
||||
|
||||
static void lcr_destroy(lcr_route route)
|
||||
{
|
||||
while(route) {
|
||||
switch_event_destroy(&route->fields);
|
||||
route=route->next;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *do_cid(switch_memory_pool_t *pool, const char *cid, const char *number, switch_core_session_t *session)
|
||||
{
|
||||
switch_regex_t *re = NULL;
|
||||
@@ -717,7 +725,7 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
|
||||
|
||||
end:
|
||||
|
||||
switch_event_destroy(&additional->fields);
|
||||
/* event is freed in lcr_destroy() switch_event_destroy(&additional->fields); */
|
||||
|
||||
return r;
|
||||
|
||||
@@ -900,6 +908,7 @@ static switch_bool_t test_profile(char *lcr_profile)
|
||||
|
||||
routes.lookup_number = "15555551212";
|
||||
routes.cid = "18005551212";
|
||||
lcr_destroy(routes.head);
|
||||
return (lcr_do_lookup(&routes) == SWITCH_STATUS_SUCCESS) ?
|
||||
SWITCH_TRUE : SWITCH_FALSE;
|
||||
}
|
||||
@@ -1378,6 +1387,7 @@ static switch_call_cause_t lcr_outgoing_channel(switch_core_session_t *session,
|
||||
if (mysession) {
|
||||
switch_core_session_rwunlock(mysession);
|
||||
}
|
||||
lcr_destroy(routes.head);
|
||||
switch_core_destroy_memory_pool(&pool);
|
||||
switch_safe_free(dest);
|
||||
|
||||
@@ -1475,6 +1485,7 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt)
|
||||
}
|
||||
|
||||
end:
|
||||
lcr_destroy(routes.head);
|
||||
if (event) {
|
||||
switch_event_destroy(&event);
|
||||
}
|
||||
@@ -1607,6 +1618,7 @@ SWITCH_STANDARD_APP(lcr_app_function)
|
||||
}
|
||||
|
||||
end:
|
||||
lcr_destroy(routes.head);
|
||||
if (routes.event) {
|
||||
switch_event_destroy(&event);
|
||||
}
|
||||
@@ -1819,6 +1831,7 @@ SWITCH_STANDARD_API(dialplan_lcr_function)
|
||||
}
|
||||
|
||||
end:
|
||||
lcr_destroy(cb_struct.head);
|
||||
if (!session) {
|
||||
if (pool) {
|
||||
switch_core_destroy_memory_pool(&pool);
|
||||
|
||||
@@ -21,3 +21,4 @@ $(CELT_LA): $(CELT_BUILDDIR)/Makefile
|
||||
cd $(CELT_BUILDDIR) && $(MAKE)
|
||||
$(TOUCH_TARGET)
|
||||
|
||||
$(MODNAME).lo: $(CELT_LA)
|
||||
@@ -6,9 +6,9 @@ OPUS_DIR=$(switch_srcdir)/libs/$(OPUS)
|
||||
OPUS_BUILDDIR=$(switch_builddir)/libs/$(OPUS)
|
||||
LOCAL_CFLAGS=-I$(OPUS_DIR)/src -g -O2
|
||||
|
||||
IETF_LA=$(OPUS_BUILDDIR)/src/.libs/libietfcodec.a
|
||||
CELT_LA=$(OPUS_BUILDDIR)/celt/libcelt/.libs/libcelt0.a
|
||||
SILK_LA=$(OPUS_BUILDDIR)/silk/.libs/libSKP_SILK_SDK.a
|
||||
IETF_LA=$(OPUS_BUILDDIR)/src/libietfcodec.la
|
||||
CELT_LA=$(OPUS_BUILDDIR)/celt/libcelt/libcelt0.la
|
||||
SILK_LA=$(OPUS_BUILDDIR)/silk/libSKP_SILK_SDK.la
|
||||
|
||||
LOCAL_LIBADD=$(IETF_LA) $(CELT_LA) $(SILK_LA) -lm -lz
|
||||
|
||||
@@ -26,3 +26,7 @@ $(IETF_LA): $(OPUS_BUILDDIR)/Makefile
|
||||
cd $(OPUS_BUILDDIR) && $(MAKE)
|
||||
$(TOUCH_TARGET)
|
||||
|
||||
$(CELT_LA): $(IETF_LA)
|
||||
$(SILK_LA): $(IETF_LA)
|
||||
|
||||
$(MODNAME).lo: $(IETF_LA) $(CELT_LA) $(SILK_LA)
|
||||
@@ -10,8 +10,10 @@ DING_DIR=$(BASE)/libs/libdingaling
|
||||
LOCAL_CFLAGS += -I$(DING_DIR)/src -I$(BASE)/libs/iksemel/include
|
||||
LOCAL_OBJS=$(DING_DIR)/src/libdingaling.o $(DING_DIR)/src/sha1.o $(IKS_LA)
|
||||
LOCAL_SOURCES=$(DING_DIR)/src/libdingaling.c $(DING_DIR)/src/sha1.c
|
||||
LOCAL_LDFLAGS=$(LIBGNUTLS_LIBS)
|
||||
include $(BASE)/build/modmake.rules
|
||||
|
||||
|
||||
$(IKS_LA): $(IKS_DIR) $(IKS_DIR)/.update
|
||||
@cd $(IKS_DIR) && $(MAKE)
|
||||
@$(TOUCH_TARGET)
|
||||
|
||||
@@ -65,19 +65,20 @@ typedef enum {
|
||||
TFLAG_CODEC_READY = (1 << 8),
|
||||
TFLAG_TRANSPORT = (1 << 9),
|
||||
TFLAG_ANSWER = (1 << 10),
|
||||
TFLAG_VAD_IN = (1 << 11),
|
||||
TFLAG_VAD_OUT = (1 << 12),
|
||||
TFLAG_VAD = (1 << 13),
|
||||
TFLAG_DO_CAND = (1 << 14),
|
||||
TFLAG_DO_DESC = (1 << 15),
|
||||
TFLAG_LANADDR = (1 << 16),
|
||||
TFLAG_AUTO = (1 << 17),
|
||||
TFLAG_DTMF = (1 << 18),
|
||||
TFLAG_TIMER = (1 << 19),
|
||||
TFLAG_TERM = (1 << 20),
|
||||
TFLAG_TRANSPORT_ACCEPT = (1 << 21),
|
||||
TFLAG_READY = (1 << 22),
|
||||
TFLAG_NAT_MAP = (1 << 22)
|
||||
TFLAG_VAD_NONE = (1 << 11),
|
||||
TFLAG_VAD_IN = (1 << 12),
|
||||
TFLAG_VAD_OUT = (1 << 13),
|
||||
TFLAG_VAD = (1 << 14),
|
||||
TFLAG_DO_CAND = (1 << 15),
|
||||
TFLAG_DO_DESC = (1 << 16),
|
||||
TFLAG_LANADDR = (1 << 17),
|
||||
TFLAG_AUTO = (1 << 18),
|
||||
TFLAG_DTMF = (1 << 19),
|
||||
TFLAG_TIMER = (1 << 20),
|
||||
TFLAG_TERM = (1 << 21),
|
||||
TFLAG_TRANSPORT_ACCEPT = (1 << 22),
|
||||
TFLAG_READY = (1 << 23),
|
||||
TFLAG_NAT_MAP = (1 << 24)
|
||||
} TFLAGS;
|
||||
|
||||
typedef enum {
|
||||
@@ -966,7 +967,7 @@ static int do_candidates(struct private_object *tech_pvt, int force)
|
||||
if (force || !switch_test_flag(tech_pvt, TFLAG_RTP_READY)) {
|
||||
ldl_candidate_t cand[1];
|
||||
char *advip = tech_pvt->profile->extip ? tech_pvt->profile->extip : tech_pvt->profile->ip;
|
||||
char *err = NULL;
|
||||
char *err = NULL, *address = NULL;
|
||||
|
||||
memset(cand, 0, sizeof(cand));
|
||||
switch_stun_random_string(tech_pvt->local_user, 16, NULL);
|
||||
@@ -975,10 +976,14 @@ static int do_candidates(struct private_object *tech_pvt, int force)
|
||||
if (switch_test_flag(tech_pvt, TFLAG_LANADDR)) {
|
||||
advip = tech_pvt->profile->ip;
|
||||
}
|
||||
address = advip;
|
||||
|
||||
if(address && !strncasecmp(address, "host:", 5)) {
|
||||
address = address + 5;
|
||||
}
|
||||
|
||||
cand[0].port = tech_pvt->adv_local_port;
|
||||
cand[0].address = advip;
|
||||
cand[0].address = address;
|
||||
|
||||
if (!strncasecmp(advip, "stun:", 5)) {
|
||||
char *stun_ip = advip + 5;
|
||||
@@ -1568,22 +1573,8 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
|
||||
channel_answer_channel(session);
|
||||
break;
|
||||
case SWITCH_MESSAGE_INDICATE_BRIDGE:
|
||||
/*
|
||||
if (tech_pvt->rtp_session && switch_test_flag(tech_pvt->profile, TFLAG_TIMER)) {
|
||||
switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "De-activate timed RTP!\n");
|
||||
//switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_TIMER_RECLOCK);
|
||||
}
|
||||
*/
|
||||
break;
|
||||
case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
|
||||
/*
|
||||
if (tech_pvt->rtp_session && switch_test_flag(tech_pvt->profile, TFLAG_TIMER)) {
|
||||
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Re-activate timed RTP!\n");
|
||||
//switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_TIMER_RECLOCK);
|
||||
}
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -2110,8 +2101,10 @@ static void set_profile_val(mdl_profile_t *profile, char *var, char *val)
|
||||
} else if (!strcasecmp(val, "both")) {
|
||||
switch_set_flag(profile, TFLAG_VAD_IN);
|
||||
switch_set_flag(profile, TFLAG_VAD_OUT);
|
||||
} else if (!strcasecmp(val, "none")) {
|
||||
switch_set_flag(profile, TFLAG_VAD_NONE);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invald option %s for VAD\n", val);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid option %s for VAD\n", val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1198,14 +1198,14 @@ static switch_status_t load_config(void)
|
||||
if (globals.outdev > -1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Switching to default output device\n");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find an input device\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find an output device\n");
|
||||
status = SWITCH_STATUS_GENERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (globals.ringdev < 0) {
|
||||
if (globals.outdev > -1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid ring device configured using output device\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid or no ring device configured, using output device as ring device\n");
|
||||
globals.ringdev = globals.outdev;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1655,6 +1655,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
||||
const char *ip = NULL, *port = NULL;
|
||||
|
||||
switch_channel_set_flag(channel, CF_PROXY_MODE);
|
||||
if (tech_pvt->rm_encoding) {
|
||||
tech_pvt->rm_encoding = NULL;
|
||||
}
|
||||
sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
|
||||
|
||||
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
|
||||
@@ -3480,6 +3483,96 @@ SWITCH_STANDARD_API(sofia_count_reg_function)
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(sofia_username_of_function)
|
||||
{
|
||||
char *data;
|
||||
char *user = NULL;
|
||||
char *domain = NULL;
|
||||
char *profile_name = NULL;
|
||||
char *p;
|
||||
char *reply = "";
|
||||
sofia_profile_t *profile = NULL;
|
||||
|
||||
if (!cmd) {
|
||||
stream->write_function(stream, "%s", "");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
data = strdup(cmd);
|
||||
switch_assert(data);
|
||||
|
||||
if ((p = strchr(data, '/'))) {
|
||||
profile_name = data;
|
||||
*p++ = '\0';
|
||||
user = p;
|
||||
} else {
|
||||
user = data;
|
||||
}
|
||||
|
||||
if ((domain = strchr(user, '@'))) {
|
||||
*domain++ = '\0';
|
||||
}
|
||||
|
||||
if (!profile_name && domain) {
|
||||
profile_name = domain;
|
||||
}
|
||||
|
||||
if (user && profile_name) {
|
||||
char *sql;
|
||||
|
||||
if (!(profile = sofia_glue_find_profile(profile_name))) {
|
||||
profile_name = domain;
|
||||
domain = NULL;
|
||||
}
|
||||
|
||||
if (!profile && profile_name) {
|
||||
profile = sofia_glue_find_profile(profile_name);
|
||||
}
|
||||
|
||||
if (profile) {
|
||||
struct cb_helper_sql2str cb;
|
||||
char username[256] = "";
|
||||
|
||||
cb.buf = username;
|
||||
cb.len = sizeof(username);
|
||||
|
||||
if (!domain || !strchr(domain, '.')) {
|
||||
domain = profile->name;
|
||||
}
|
||||
|
||||
switch_assert(!zstr(user));
|
||||
|
||||
sql = switch_mprintf("select sip_username "
|
||||
"from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
|
||||
user, domain, domain);
|
||||
|
||||
switch_assert(sql);
|
||||
|
||||
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sql2str_callback, &cb);
|
||||
switch_safe_free(sql);
|
||||
if (!zstr(username)) {
|
||||
stream->write_function(stream, "%s", username);
|
||||
} else {
|
||||
stream->write_function(stream, "");
|
||||
}
|
||||
reply = NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
stream->write_function(stream, "%s", reply);
|
||||
}
|
||||
|
||||
switch_safe_free(data);
|
||||
|
||||
if (profile) {
|
||||
sofia_glue_release_profile(profile);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void select_from_profile(sofia_profile_t *profile,
|
||||
const char *user,
|
||||
const char *domain,
|
||||
@@ -3987,6 +4080,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
|
||||
const char *hval = NULL;
|
||||
char *not_const = NULL;
|
||||
int cid_locked = 0;
|
||||
switch_channel_t *o_channel = NULL;
|
||||
|
||||
*new_session = NULL;
|
||||
|
||||
@@ -4015,6 +4109,11 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
|
||||
|
||||
nchannel = switch_core_session_get_channel(nsession);
|
||||
|
||||
if (session) {
|
||||
o_channel = switch_core_session_get_channel(session);
|
||||
}
|
||||
|
||||
|
||||
if ((hval = switch_event_get_header(var_event, "sip_invite_to_uri"))) {
|
||||
dest_to = switch_core_session_strdup(nsession, hval);
|
||||
}
|
||||
@@ -4121,7 +4220,23 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
|
||||
gateway_ptr->ob_calls++;
|
||||
|
||||
if (!zstr(gateway_ptr->from_domain) && !switch_channel_get_variable(nchannel, "sip_invite_domain")) {
|
||||
switch_channel_set_variable(nchannel, "sip_invite_domain", gateway_ptr->from_domain);
|
||||
|
||||
if (!strcasecmp(gateway_ptr->from_domain, "auto-aleg-full")) {
|
||||
const char *sip_full_from = switch_channel_get_variable(o_channel, "sip_full_from");
|
||||
|
||||
if (!zstr(sip_full_from)) {
|
||||
switch_channel_set_variable(nchannel, "sip_force_full_from", sip_full_from);
|
||||
}
|
||||
|
||||
} else if (!strcasecmp(gateway_ptr->from_domain, "auto-aleg-domain")) {
|
||||
const char *sip_from_host = switch_channel_get_variable(o_channel, "sip_from_host");
|
||||
|
||||
if (!zstr(sip_from_host)) {
|
||||
switch_channel_set_variable(nchannel, "sip_invite_domain", sip_from_host);
|
||||
}
|
||||
} else {
|
||||
switch_channel_set_variable(nchannel, "sip_invite_domain", gateway_ptr->from_domain);
|
||||
}
|
||||
}
|
||||
|
||||
if (!zstr(gateway_ptr->outbound_sticky_proxy) && !switch_channel_get_variable(nchannel, "sip_route_uri")) {
|
||||
@@ -4320,7 +4435,6 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
|
||||
}
|
||||
|
||||
if (session) {
|
||||
switch_channel_t *o_channel = switch_core_session_get_channel(session);
|
||||
const char *vval = NULL;
|
||||
|
||||
if ((vval = switch_channel_get_variable(o_channel, "sip_auto_answer")) && switch_true(vval)) {
|
||||
@@ -5090,6 +5204,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
|
||||
switch_console_add_complete_func("::sofia::list_profile_gateway", list_profile_gateway);
|
||||
|
||||
|
||||
SWITCH_ADD_API(api_interface, "sofia_username_of", "Sofia Username Lookup", sofia_username_of_function, "[profile/]<user>@<domain>");
|
||||
SWITCH_ADD_API(api_interface, "sofia_contact", "Sofia Contacts", sofia_contact_function, "[profile/]<user>@<domain>");
|
||||
SWITCH_ADD_API(api_interface, "sofia_count_reg", "Count Sofia registration", sofia_count_reg_function, "[profile/]<user>@<domain>");
|
||||
SWITCH_ADD_API(api_interface, "sofia_dig", "SIP DIG", sip_dig_function, "<url>");
|
||||
|
||||
@@ -564,7 +564,8 @@ struct sofia_profile {
|
||||
uint32_t reg_acl_count;
|
||||
char *nat_acl[SOFIA_MAX_ACL];
|
||||
uint32_t nat_acl_count;
|
||||
int rport_level;
|
||||
int server_rport_level;
|
||||
int client_rport_level;
|
||||
sofia_presence_type_t pres_type;
|
||||
sofia_media_options_t media_options;
|
||||
uint32_t force_subscription_expires;
|
||||
|
||||
@@ -76,14 +76,15 @@ void sofia_handle_sip_r_notify(switch_core_session_t *session, int status,
|
||||
char const *phrase,
|
||||
nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[])
|
||||
{
|
||||
#if 0
|
||||
|
||||
if (status >= 300 && sip && sip->sip_call_id) {
|
||||
char *sql;
|
||||
sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", sip->sip_call_id->i_id);
|
||||
switch_assert(sql != NULL);
|
||||
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
|
||||
nua_handle_destroy(nh);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#define url_set_chanvars(session, url, varprefix) _url_set_chanvars(session, url, #varprefix "_user", #varprefix "_host", #varprefix "_port", #varprefix "_uri", #varprefix "_params")
|
||||
@@ -1275,6 +1276,11 @@ static void sofia_perform_profile_start_failure(sofia_profile_t *profile, char *
|
||||
}
|
||||
}
|
||||
|
||||
/* not a static function so that it's still visible on stacktraces */
|
||||
void watchdog_triggered_abort(void) {
|
||||
abort();
|
||||
}
|
||||
|
||||
#define sofia_profile_start_failure(p, xp) sofia_perform_profile_start_failure(p, xp, __FILE__, __LINE__)
|
||||
|
||||
|
||||
@@ -1390,10 +1396,10 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
|
||||
}
|
||||
|
||||
if (event_fail || step_fail) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s: SIP STACK FAILURE DETECTED!\n"
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s: SIP STACK FAILURE DETECTED BY WATCHDOG!\n"
|
||||
"GOODBYE CRUEL WORLD, I'M LEAVING YOU TODAY....GOODBYE, GOODBYE, GOOD BYE\n", profile->name);
|
||||
switch_yield(2000000);
|
||||
abort();
|
||||
watchdog_triggered_abort();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1516,7 +1522,8 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
|
||||
TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_NAPTR),
|
||||
NTATAG_USE_NAPTR(0)),
|
||||
NTATAG_DEFAULT_PROXY(profile->outbound_proxy),
|
||||
NTATAG_SERVER_RPORT(profile->rport_level),
|
||||
NTATAG_SERVER_RPORT(profile->server_rport_level),
|
||||
NTATAG_CLIENT_RPORT(profile->client_rport_level),
|
||||
TPTAG_LOG(sofia_test_flag(profile, TFLAG_TPORT_LOG)),
|
||||
TAG_IF(sofia_test_pflag(profile, PFLAG_SIPCOMPACT),
|
||||
NTATAG_SIPFLAGS(MSG_DO_COMPACT)),
|
||||
@@ -1579,7 +1586,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
|
||||
node->nua = nua_create(profile->s_root, /* Event loop */
|
||||
sofia_event_callback, /* Callback for processing events */
|
||||
profile, /* Additional data to pass to callback */
|
||||
NTATAG_SERVER_RPORT(profile->rport_level), NUTAG_URL(node->url), TAG_END()); /* Last tag should always finish the sequence */
|
||||
NTATAG_SERVER_RPORT(profile->server_rport_level), NUTAG_URL(node->url), TAG_END()); /* Last tag should always finish the sequence */
|
||||
|
||||
nua_set_params(node->nua,
|
||||
NUTAG_APPL_METHOD("OPTIONS"),
|
||||
@@ -2342,7 +2349,6 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
|
||||
}
|
||||
|
||||
/* you could change profile->foo here if it was a minor change like context or dialplan ... */
|
||||
profile->rport_level = 1; /* default setting */
|
||||
profile->acl_count = 0;
|
||||
profile->reg_acl_count = 0;
|
||||
profile->proxy_acl_count = 0;
|
||||
@@ -2493,12 +2499,6 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
|
||||
} else {
|
||||
profile->dtmf_type = DTMF_NONE;
|
||||
}
|
||||
} else if (!strcasecmp(var, "NDLB-force-rport")) {
|
||||
if (val && !strcasecmp(val, "safe")) {
|
||||
profile->rport_level = 3;
|
||||
} else if (switch_true(val)) {
|
||||
profile->rport_level = 2;
|
||||
}
|
||||
} else if (!strcasecmp(var, "caller-id-type")) {
|
||||
profile->cid_type = sofia_cid_name2type(val);
|
||||
} else if (!strcasecmp(var, "record-template")) {
|
||||
@@ -3064,7 +3064,8 @@ switch_status_t config_sofia(int reload, char *profile_name)
|
||||
profile->dtmf_duration = 100;
|
||||
profile->tls_version = 0;
|
||||
profile->mflags = MFLAG_REFER | MFLAG_REGISTER;
|
||||
profile->rport_level = 1;
|
||||
profile->server_rport_level = 1;
|
||||
profile->client_rport_level = 1;
|
||||
sofia_set_pflag(profile, PFLAG_STUN_ENABLED);
|
||||
sofia_set_pflag(profile, PFLAG_DISABLE_100REL);
|
||||
profile->auto_restart = 1;
|
||||
@@ -3206,9 +3207,19 @@ switch_status_t config_sofia(int reload, char *profile_name)
|
||||
}
|
||||
} else if (!strcasecmp(var, "NDLB-force-rport")) {
|
||||
if (val && !strcasecmp(val, "safe")) {
|
||||
profile->rport_level = 3;
|
||||
profile->server_rport_level = 3;
|
||||
profile->client_rport_level = 1;
|
||||
} else if (val && !strcasecmp(val, "disabled")) {
|
||||
profile->server_rport_level = 0;
|
||||
profile->client_rport_level = 0;
|
||||
} else if (val && !strcasecmp(val, "client-only")) {
|
||||
profile->client_rport_level = 1;
|
||||
} else if (val && !strcasecmp(val, "server-only")) {
|
||||
profile->client_rport_level = 0;
|
||||
profile->client_rport_level = 1;
|
||||
} else if (switch_true(val)) {
|
||||
profile->rport_level = 2;
|
||||
profile->server_rport_level = 2;
|
||||
profile->client_rport_level = 1;
|
||||
}
|
||||
} else if (!strcasecmp(var, "auto-rtp-bugs")) {
|
||||
sofia_glue_parse_rtp_bugs(&profile->auto_rtp_bugs, val);
|
||||
@@ -4404,7 +4415,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MODE) ||
|
||||
switch_channel_test_flag(channel, CF_PROXY_MEDIA) ||
|
||||
(sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38)) {
|
||||
(sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && (has_t38 || status > 299))) {
|
||||
|
||||
if (sofia_test_flag(tech_pvt, TFLAG_SENT_UPDATE)) {
|
||||
sofia_clear_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
|
||||
@@ -4413,6 +4424,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
|
||||
const char *r_sdp = NULL;
|
||||
switch_core_session_message_t *msg;
|
||||
private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
|
||||
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
|
||||
|
||||
if (sip->sip_payload && sip->sip_payload->pl_data &&
|
||||
sip->sip_content_type && sip->sip_content_type->c_subtype && switch_stristr("sdp", sip->sip_content_type->c_subtype)) {
|
||||
@@ -4423,9 +4435,14 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing %d %s to other leg\n", status, phrase);
|
||||
|
||||
if (status == 200 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38 && sip->sip_payload && sip->sip_payload->pl_data) {
|
||||
if (status > 299) {
|
||||
switch_channel_set_private(channel, "t38_options", NULL);
|
||||
switch_channel_set_private(other_channel, "t38_options", NULL);
|
||||
sofia_clear_flag(tech_pvt, TFLAG_T38_PASSTHRU);
|
||||
sofia_clear_flag(other_tech_pvt, TFLAG_T38_PASSTHRU);
|
||||
} else if (status == 200 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38 && sip->sip_payload && sip->sip_payload->pl_data) {
|
||||
switch_t38_options_t *t38_options = sofia_glue_extract_t38_options(session, sip->sip_payload->pl_data);
|
||||
|
||||
|
||||
if (!t38_options) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_WARNING, "%s Error parsing SDP:\n%s\n",
|
||||
switch_channel_get_name(tech_pvt->channel), sip->sip_payload->pl_data);
|
||||
@@ -4912,7 +4929,11 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
match = sofia_glue_negotiate_sdp(session, r_sdp);
|
||||
}
|
||||
|
||||
if (match) {
|
||||
if (!match) {
|
||||
if (switch_channel_get_state(channel) != CS_NEW) {
|
||||
nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
|
||||
}
|
||||
} else {
|
||||
nua_handle_t *bnh;
|
||||
sip_replaces_t *replaces;
|
||||
su_home_t *home = NULL;
|
||||
@@ -4920,6 +4941,8 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
sofia_set_flag_locked(tech_pvt, TFLAG_READY);
|
||||
if (switch_channel_get_state(channel) == CS_NEW) {
|
||||
switch_channel_set_state(channel, CS_INIT);
|
||||
} else {
|
||||
nua_respond(tech_pvt->nh, SIP_200_OK, TAG_END());
|
||||
}
|
||||
sofia_set_flag(tech_pvt, TFLAG_SDP);
|
||||
if (replaces_str) {
|
||||
@@ -5688,6 +5711,11 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
|
||||
switch_core_event_hook_add_state_change(a_session, xfer_hanguphook);
|
||||
switch_channel_set_variable(a_channel, "att_xfer_kill_uuid", switch_core_session_get_uuid(b_session));
|
||||
|
||||
if (profile->media_options & MEDIA_OPT_BYPASS_AFTER_ATT_XFER) {
|
||||
switch_channel_set_flag(a_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
|
||||
}
|
||||
|
||||
|
||||
if ((tmp = switch_channel_get_hold_music(a_channel))) {
|
||||
moh = tmp;
|
||||
}
|
||||
@@ -5747,6 +5775,12 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
|
||||
switch_core_session_rwunlock(tmp);
|
||||
}
|
||||
|
||||
if ((profile->media_options & MEDIA_OPT_BYPASS_AFTER_ATT_XFER) && (tmp = switch_core_session_locate(br_a))) {
|
||||
switch_channel_t *tchannel = switch_core_session_get_channel(tmp);
|
||||
switch_channel_set_flag(tchannel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
|
||||
switch_core_session_rwunlock(tmp);
|
||||
}
|
||||
|
||||
switch_ivr_uuid_bridge(br_b, br_a);
|
||||
switch_channel_set_variable(channel_b, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
|
||||
nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
|
||||
@@ -6129,7 +6163,7 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
|
||||
/* Barf if we didn't get our private */
|
||||
assert(switch_core_session_get_private(session));
|
||||
|
||||
if (sip->sip_content_type && sip->sip_content_type->c_subtype && sip->sip_content_type->c_type &&
|
||||
if (sip && sip->sip_content_type && sip->sip_content_type->c_subtype && sip->sip_content_type->c_type &&
|
||||
!strncasecmp(sip->sip_content_type->c_type, "message", 7) &&
|
||||
!strcasecmp(sip->sip_content_type->c_subtype, "update_display")) {
|
||||
sofia_update_callee_id(session, profile, sip, SWITCH_TRUE);
|
||||
|
||||
@@ -505,7 +505,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32
|
||||
ptime = tech_pvt->read_codec.implementation->microseconds_per_packet / 1000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (tech_pvt->dtmf_type == DTMF_2833 && tech_pvt->te > 95) {
|
||||
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", tech_pvt->te, tech_pvt->te);
|
||||
}
|
||||
@@ -729,6 +729,8 @@ void sofia_glue_tech_prepare_codecs(private_object_t *tech_pvt)
|
||||
return;
|
||||
}
|
||||
|
||||
tech_pvt->payload_space = 0;
|
||||
|
||||
switch_assert(tech_pvt->session != NULL);
|
||||
|
||||
if ((abs = switch_channel_get_variable(tech_pvt->channel, "absolute_codec_string"))) {
|
||||
@@ -1893,6 +1895,8 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
|
||||
const char *invite_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_to");
|
||||
const char *handle_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_handle_full_from");
|
||||
const char *handle_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_handle_full_to");
|
||||
const char *force_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_from");
|
||||
const char *force_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_to");
|
||||
char *mp = NULL, *mp_type = NULL;
|
||||
|
||||
rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER);
|
||||
@@ -2125,6 +2129,15 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
|
||||
}
|
||||
|
||||
|
||||
if (force_full_from) {
|
||||
from_str = (char *) force_full_from;
|
||||
}
|
||||
|
||||
if (force_full_to) {
|
||||
to_str = (char *) force_full_to;
|
||||
}
|
||||
|
||||
|
||||
if (invite_req_uri) {
|
||||
url_str = (char *) invite_req_uri;
|
||||
}
|
||||
@@ -4754,6 +4767,11 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
|
||||
switch_rtp_set_telephony_recv_event(tech_pvt->rtp_session, te);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Disable 2833 dtmf\n");
|
||||
switch_channel_set_variable(tech_pvt->channel, "dtmf_type", "none");
|
||||
tech_pvt->dtmf_type = DTMF_NONE;
|
||||
te = tech_pvt->recv_te = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -5210,12 +5228,14 @@ void sofia_glue_del_profile(sofia_profile_t *profile)
|
||||
}
|
||||
|
||||
for (gp = profile->gateways; gp; gp = gp->next) {
|
||||
char *pkey = switch_mprintf("%s::%s", profile->name, gp->name);
|
||||
|
||||
switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->name);
|
||||
switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->register_from);
|
||||
switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->register_contact);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "deleted gateway %s\n", gp->name);
|
||||
profile->gateways = NULL;
|
||||
switch_core_hash_delete(mod_sofia_globals.gateway_hash, pkey);
|
||||
switch_safe_free(pkey);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "deleted gateway %s from profile %s\n", gp->name, profile->name);
|
||||
}
|
||||
profile->gateways = NULL;
|
||||
}
|
||||
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
|
||||
}
|
||||
|
||||
@@ -1506,9 +1506,9 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char *
|
||||
stream.write_function(&stream,
|
||||
"<?xml version=\"1.0\"?>\n"
|
||||
"<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" "
|
||||
"version=\"%s\" state=\"%s\" entity=\"%s\">\n",
|
||||
version,
|
||||
zstr(uuid) ? "partial" : "full", clean_id);
|
||||
"version=\"%s\" state=\"partial\" entity=\"%s\">\n", version, clean_id);
|
||||
|
||||
|
||||
}
|
||||
|
||||
//if (strcasecmp(event_status, "Registered")) {
|
||||
|
||||
@@ -800,7 +800,7 @@ void sofia_reg_auth_challenge(nua_t *nua, sofia_profile_t *profile, nua_handle_t
|
||||
|
||||
sql = switch_mprintf("insert into sip_authentication (nonce,expires,profile_name,hostname, last_nc) "
|
||||
"values('%q', %ld, '%q', '%q', 0)", uuid_str,
|
||||
switch_epoch_time_now(NULL) + (profile->nonce_ttl ? profile->nonce_ttl : DEFAULT_NONCE_TTL),
|
||||
(long) switch_epoch_time_now(NULL) + (profile->nonce_ttl ? profile->nonce_ttl : DEFAULT_NONCE_TTL),
|
||||
profile->name, mod_sofia_globals.hostname);
|
||||
switch_assert(sql != NULL);
|
||||
sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex);
|
||||
@@ -1104,7 +1104,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
|
||||
to_user = force_user;
|
||||
}
|
||||
|
||||
if (profile->rport_level == 3 && sip->sip_user_agent &&
|
||||
if (profile->server_rport_level == 3 && sip->sip_user_agent &&
|
||||
sip->sip_user_agent->g_string && !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7)) {
|
||||
if (sip && sip->sip_via) {
|
||||
const char *host = sip->sip_via->v_host;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
BASE=../../../..
|
||||
|
||||
ZMQ=zeromq-2.1.3
|
||||
|
||||
ZMQ_BASEURL=http://download.zeromq.org
|
||||
|
||||
ZMQ_DIR=$(switch_srcdir)/libs/$(ZMQ)
|
||||
ZMQ_BUILDDIR=$(switch_builddir)/libs/$(ZMQ)
|
||||
LOCAL_CFLAGS=-I$(ZMQ_DIR)/include
|
||||
ZMQ_LA=$(ZMQ_BUILDDIR)/src/libzmq.la
|
||||
LOCAL_LIBADD=$(ZMQ_LA)
|
||||
|
||||
include $(BASE)/build/modmake.rules
|
||||
|
||||
$(ZMQ_DIR):
|
||||
$(GETLIB) $(ZMQ_BASEURL) $(ZMQ).tar.gz
|
||||
cd $(ZMQ_DIR) && ./autogen.sh
|
||||
|
||||
$(ZMQ_BUILDDIR)/Makefile: $(ZMQ_DIR)
|
||||
mkdir -p $(ZMQ_DIR)
|
||||
cd $(ZMQ_BUILDDIR) && $(DEFAULT_VARS) $(ZMQ_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(ZMQ_DIR)
|
||||
$(TOUCH_TARGET)
|
||||
|
||||
$(ZMQ_LA): $(ZMQ_BUILDDIR)/Makefile
|
||||
cd $(ZMQ_BUILDDIR) && $(MAKE)
|
||||
$(TOUCH_TARGET)
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
#include <switch.h>
|
||||
#include <zmq.hpp>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
namespace mod_event_zmq {
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(load);
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(shutdown);
|
||||
SWITCH_MODULE_RUNTIME_FUNCTION(runtime);
|
||||
|
||||
extern "C" {
|
||||
SWITCH_MODULE_DEFINITION(mod_event_zmq, load, shutdown, runtime);
|
||||
};
|
||||
|
||||
// Handles publishing events out to clients
|
||||
class ZmqEventPublisher {
|
||||
public:
|
||||
ZmqEventPublisher() :
|
||||
context(1),
|
||||
event_publisher(context, ZMQ_PUB)
|
||||
{
|
||||
event_publisher.bind("tcp://*:5556");
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Listening for clients\n");
|
||||
}
|
||||
|
||||
void PublishEvent(const switch_event_t *event) {
|
||||
// Serialize the event into a JSON string
|
||||
char* pjson;
|
||||
switch_event_serialize_json(const_cast<switch_event_t*>(event), &pjson);
|
||||
|
||||
// Use the JSON string as the message body
|
||||
zmq::message_t msg(pjson, strlen(pjson), free_message_data, NULL);
|
||||
|
||||
// Send the message
|
||||
event_publisher.send(msg);
|
||||
}
|
||||
|
||||
private:
|
||||
static void free_message_data(void *data, void *hint) {
|
||||
free (data);
|
||||
}
|
||||
|
||||
zmq::context_t context;
|
||||
zmq::socket_t event_publisher;
|
||||
};
|
||||
|
||||
// Handles global inititalization and teardown of the module
|
||||
class ZmqModule {
|
||||
public:
|
||||
ZmqModule(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) :
|
||||
_running(false) {
|
||||
// Subscribe to all switch events of any subclass
|
||||
// Store a pointer to ourself in the user data
|
||||
if (switch_event_bind_removable(modname, SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, event_handler, (void*)this, &_node)
|
||||
!= SWITCH_STATUS_SUCCESS) {
|
||||
throw std::runtime_error("Couldn't bind to switch events.");
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Subscribed to events\n");
|
||||
|
||||
// Create our module interface registration
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Module loaded\n");
|
||||
}
|
||||
|
||||
void Listen() {
|
||||
if(_running)
|
||||
return;
|
||||
|
||||
_publisher.reset(new ZmqEventPublisher());
|
||||
_running = true;
|
||||
|
||||
while(_running) {
|
||||
switch_yield(100000);
|
||||
}
|
||||
}
|
||||
|
||||
~ZmqModule() {
|
||||
// Unsubscribe from the switch events
|
||||
_running = false;
|
||||
switch_event_unbind(&_node);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Module shut down\n");
|
||||
}
|
||||
|
||||
private:
|
||||
// Dispatches events to the publisher
|
||||
static void event_handler(switch_event_t *event) {
|
||||
try {
|
||||
ZmqModule *module = (ZmqModule*)event->bind_user_data;
|
||||
if(module->_publisher.get())
|
||||
module->_publisher->PublishEvent(event);
|
||||
} catch(std::exception ex) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error publishing event via 0MQ: %s\n", ex.what());
|
||||
} catch(...) { // Exceptions must not propogate to C caller
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown error publishing event via 0MQ\n");
|
||||
}
|
||||
}
|
||||
|
||||
switch_event_node_t *_node;
|
||||
std::auto_ptr<ZmqEventPublisher> _publisher;
|
||||
bool _running;
|
||||
};
|
||||
|
||||
//*****************************//
|
||||
// GLOBALS //
|
||||
//*****************************//
|
||||
std::auto_ptr<ZmqModule> module;
|
||||
|
||||
|
||||
//*****************************//
|
||||
// Module interface funtions //
|
||||
//*****************************//
|
||||
SWITCH_MODULE_LOAD_FUNCTION(load) {
|
||||
try {
|
||||
module.reset(new ZmqModule(module_interface, pool));
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
} catch(...) { // Exceptions must not propogate to C caller
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error loading 0MQ module\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SWITCH_MODULE_RUNTIME_FUNCTION(runtime) {
|
||||
try {
|
||||
// Begin listening for clients
|
||||
module->Listen();
|
||||
} catch(std::exception &ex) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error listening for clients: %s\n", ex.what());
|
||||
} catch(...) { // Exceptions must not propogate to C caller
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown error listening for clients\n");
|
||||
}
|
||||
|
||||
// Tell the switch to stop calling this runtime loop
|
||||
return SWITCH_STATUS_TERM;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(shutdown) {
|
||||
try {
|
||||
// Free the module object
|
||||
module.reset();
|
||||
} catch(...) { // Exceptions must not propogate to C caller
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error shutting down module\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Cesar Cepeda <cesar@auronix.com>
|
||||
*
|
||||
*
|
||||
* mod_file_string.c -- Local Streaming Audio
|
||||
*
|
||||
*/
|
||||
#include <switch.h>
|
||||
/* for apr_pstrcat */
|
||||
#define DEFAULT_PREBUFFER_SIZE 1024 * 64
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_file_string_load);
|
||||
|
||||
SWITCH_MODULE_DEFINITION(mod_file_string, mod_file_string_load, NULL, NULL);
|
||||
|
||||
|
||||
struct file_string_source;
|
||||
|
||||
static struct {
|
||||
switch_mutex_t *mutex;
|
||||
switch_hash_t *source_hash;
|
||||
} globals;
|
||||
|
||||
struct file_string_context {
|
||||
char *argv[128];
|
||||
int argc;
|
||||
int index;
|
||||
int samples;
|
||||
switch_file_handle_t fh;
|
||||
};
|
||||
|
||||
typedef struct file_string_context file_string_context_t;
|
||||
|
||||
|
||||
static int next_file(switch_file_handle_t *handle)
|
||||
{
|
||||
file_string_context_t *context = handle->private_info;
|
||||
char *file;
|
||||
const char *prefix = handle->prefix;
|
||||
|
||||
top:
|
||||
|
||||
context->index++;
|
||||
|
||||
if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) {
|
||||
switch_core_file_close(&context->fh);
|
||||
}
|
||||
|
||||
if (context->index >= context->argc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (!prefix) {
|
||||
if (!(prefix = switch_core_get_variable_pdup("sound_prefix", handle->memory_pool))) {
|
||||
prefix = SWITCH_GLOBAL_dirs.sounds_dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (!prefix || switch_is_file_path(context->argv[context->index])) {
|
||||
file = context->argv[context->index];
|
||||
} else {
|
||||
file = switch_core_sprintf(handle->memory_pool, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, context->argv[context->index]);
|
||||
}
|
||||
|
||||
if (switch_core_file_open(&context->fh,
|
||||
file, handle->channels, handle->samplerate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
|
||||
goto top;
|
||||
}
|
||||
|
||||
handle->samples = context->fh.samples;
|
||||
handle->samplerate = context->fh.samplerate;
|
||||
handle->channels = context->fh.channels;
|
||||
handle->format = context->fh.format;
|
||||
handle->sections = context->fh.sections;
|
||||
handle->seekable = context->fh.seekable;
|
||||
handle->speed = context->fh.speed;
|
||||
handle->interval = context->fh.interval;
|
||||
|
||||
if (context->index == 0) {
|
||||
context->samples = (handle->samplerate / 1000) * 250;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t file_string_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
|
||||
{
|
||||
file_string_context_t *context = handle->private_info;
|
||||
|
||||
if (samples == 0 && whence == SEEK_SET) {
|
||||
context->index = -1;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!handle->seekable) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File is not seekable\n");
|
||||
return SWITCH_STATUS_NOTIMPL;
|
||||
}
|
||||
|
||||
return switch_core_file_seek(&context->fh, cur_sample, samples, whence);
|
||||
}
|
||||
|
||||
static switch_status_t file_string_file_open(switch_file_handle_t *handle, const char *path)
|
||||
{
|
||||
file_string_context_t *context;
|
||||
char *file_dup;
|
||||
|
||||
if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "This format does not support writing!\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
context = switch_core_alloc(handle->memory_pool, sizeof(*context));
|
||||
|
||||
file_dup = switch_core_strdup(handle->memory_pool, path);
|
||||
context->argc = switch_separate_string(file_dup, '!', context->argv, (sizeof(context->argv) / sizeof(context->argv[0])));
|
||||
context->index = -1;
|
||||
|
||||
handle->private_info = context;
|
||||
|
||||
return next_file(handle) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
static switch_status_t file_string_file_close(switch_file_handle_t *handle)
|
||||
{
|
||||
file_string_context_t *context = handle->private_info;
|
||||
|
||||
switch_core_file_close(&context->fh);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t file_string_file_read(switch_file_handle_t *handle, void *data, size_t *len)
|
||||
{
|
||||
file_string_context_t *context = handle->private_info;
|
||||
switch_status_t status;
|
||||
size_t llen = *len;
|
||||
|
||||
if (context->samples > 0) {
|
||||
if (*len > (size_t) context->samples) {
|
||||
*len = context->samples;
|
||||
}
|
||||
|
||||
context->samples -= *len;
|
||||
switch_generate_sln_silence((int16_t *) data, *len, 400);
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
} else {
|
||||
status = switch_core_file_read(&context->fh, data, len);
|
||||
}
|
||||
|
||||
if (status != SWITCH_STATUS_SUCCESS) {
|
||||
if (!next_file(handle)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
*len = llen;
|
||||
status = switch_core_file_read(&context->fh, data, len);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Registration */
|
||||
|
||||
static char *supported_formats[SWITCH_MAX_CODECS] = { 0 };
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_file_string_load)
|
||||
{
|
||||
switch_file_interface_t *file_interface;
|
||||
supported_formats[0] = "file_string";
|
||||
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
|
||||
file_interface->interface_name = modname;
|
||||
file_interface->extens = supported_formats;
|
||||
file_interface->file_open = file_string_file_open;
|
||||
file_interface->file_close = file_string_file_close;
|
||||
file_interface->file_read = file_string_file_read;
|
||||
file_interface->file_seek = file_string_file_seek;
|
||||
|
||||
memset(&globals, 0, sizeof(globals));
|
||||
/* indicate that the module should continue to be loaded */
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
@@ -142,11 +142,6 @@ void Session::do_hangup_hook()
|
||||
}
|
||||
|
||||
docall(L, arg_count, 1, 1);
|
||||
err = lua_tostring(L, -1);
|
||||
|
||||
if (!zstr(err)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err);
|
||||
}
|
||||
|
||||
if (channel) {
|
||||
switch_channel_set_private(channel, "CoreSession", NULL);
|
||||
|
||||
@@ -127,10 +127,23 @@ static switch_status_t de_say_general_count(switch_core_session_t *session, char
|
||||
int in;
|
||||
int x = 0;
|
||||
int places[9] = { 0 };
|
||||
char sbuf[13] = "";
|
||||
char sbuf[128] = "";
|
||||
switch_status_t status;
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -158,14 +171,6 @@ static switch_status_t de_say_general_count(switch_core_session_t *session, char
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
case SSM_ITERATED:
|
||||
{
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -327,7 +332,7 @@ static switch_status_t de_say_money(switch_core_session_t *session, char *tosay,
|
||||
char *dollars = NULL;
|
||||
char *cents = NULL;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_say_en_load);
|
||||
SWITCH_MODULE_DEFINITION(mod_say_en, mod_say_en_load, NULL, NULL);
|
||||
|
||||
#define say_num(num, meth) { \
|
||||
|
||||
#define say_num(_sh, num, meth) { \
|
||||
char tmp[80]; \
|
||||
switch_status_t tstatus; \
|
||||
switch_say_method_t smeth = say_args->method; \
|
||||
@@ -59,7 +60,7 @@ SWITCH_MODULE_DEFINITION(mod_say_en, mod_say_en_load, NULL, NULL);
|
||||
say_args->type = SST_ITEMS; say_args->method = meth; \
|
||||
switch_snprintf(tmp, sizeof(tmp), "%u", (unsigned)num); \
|
||||
if ((tstatus = \
|
||||
en_say_general_count(session, tmp, say_args, args)) \
|
||||
en_say_general_count(_sh, tmp, say_args)) \
|
||||
!= SWITCH_STATUS_SUCCESS) { \
|
||||
return tstatus; \
|
||||
} \
|
||||
@@ -67,57 +68,44 @@ SWITCH_MODULE_DEFINITION(mod_say_en, mod_say_en_load, NULL, NULL);
|
||||
} \
|
||||
|
||||
|
||||
#define say_file(...) { \
|
||||
char tmp[80]; \
|
||||
switch_status_t tstatus; \
|
||||
switch_snprintf(tmp, sizeof(tmp), __VA_ARGS__); \
|
||||
if ((tstatus = \
|
||||
switch_ivr_play_file(session, NULL, tmp, args)) \
|
||||
!= SWITCH_STATUS_SUCCESS){ \
|
||||
return tstatus; \
|
||||
} \
|
||||
if (!switch_channel_ready(switch_core_session_get_channel(session))) { \
|
||||
return SWITCH_STATUS_FALSE; \
|
||||
}} \
|
||||
|
||||
|
||||
static switch_status_t play_group(switch_say_method_t method, int a, int b, int c, char *what, switch_core_session_t *session, switch_input_args_t *args)
|
||||
static switch_status_t play_group(switch_say_method_t method, int a, int b, int c, char *what, switch_say_file_handle_t *sh)
|
||||
{
|
||||
|
||||
if (a) {
|
||||
say_file("digits/%d.wav", a);
|
||||
say_file("digits/hundred.wav");
|
||||
switch_say_file(sh, "digits/%d", a);
|
||||
switch_say_file(sh, "digits/hundred");
|
||||
}
|
||||
|
||||
if (b) {
|
||||
if (b > 1) {
|
||||
if ((c == 0) && (method == SSM_COUNTED)) {
|
||||
say_file("digits/h-%d0.wav", b);
|
||||
switch_say_file(sh, "digits/h-%d0", b);
|
||||
} else {
|
||||
say_file("digits/%d0.wav", b);
|
||||
switch_say_file(sh, "digits/%d0", b);
|
||||
}
|
||||
} else {
|
||||
say_file("digits/%d%d.wav", b, c);
|
||||
switch_say_file(sh, "digits/%d%d", b, c);
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (c) {
|
||||
if (method == SSM_COUNTED) {
|
||||
say_file("digits/h-%d.wav", c);
|
||||
switch_say_file(sh, "digits/h-%d", c);
|
||||
} else {
|
||||
say_file("digits/%d.wav", c);
|
||||
switch_say_file(sh, "digits/%d", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (what && (a || b || c)) {
|
||||
say_file(what);
|
||||
switch_say_file(sh, what);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t en_say_general_count(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
static switch_status_t en_say_general_count(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
int in;
|
||||
int x = 0;
|
||||
@@ -126,10 +114,10 @@ static switch_status_t en_say_general_count(switch_core_session_t *session, char
|
||||
switch_status_t status;
|
||||
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
switch_say_file(sh, "digits/%c", *p);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
@@ -138,7 +126,7 @@ static switch_status_t en_say_general_count(switch_core_session_t *session, char
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -156,13 +144,13 @@ static switch_status_t en_say_general_count(switch_core_session_t *session, char
|
||||
switch (say_args->method) {
|
||||
case SSM_COUNTED:
|
||||
case SSM_PRONOUNCED:
|
||||
if ((status = play_group(SSM_PRONOUNCED, places[8], places[7], places[6], "digits/million.wav", session, args)) != SWITCH_STATUS_SUCCESS) {
|
||||
if ((status = play_group(SSM_PRONOUNCED, places[8], places[7], places[6], "digits/million", sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
if ((status = play_group(SSM_PRONOUNCED, places[5], places[4], places[3], "digits/thousand.wav", session, args)) != SWITCH_STATUS_SUCCESS) {
|
||||
if ((status = play_group(SSM_PRONOUNCED, places[5], places[4], places[3], "digits/thousand", sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
if ((status = play_group(say_args->method, places[2], places[1], places[0], NULL, session, args)) != SWITCH_STATUS_SUCCESS) {
|
||||
if ((status = play_group(say_args->method, places[2], places[1], places[0], NULL, sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
@@ -170,20 +158,21 @@ static switch_status_t en_say_general_count(switch_core_session_t *session, char
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
say_file("digits/0.wav");
|
||||
switch_say_file(sh, "digits/0");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t en_say_time(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
static switch_status_t en_say_time(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
int32_t t;
|
||||
switch_time_t target = 0, target_now = 0;
|
||||
switch_time_exp_t tm, tm_now;
|
||||
uint8_t say_date = 0, say_time = 0, say_year = 0, say_month = 0, say_dow = 0, say_day = 0, say_yesterday = 0, say_today = 0;
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
const char *tz = switch_channel_get_variable(channel, "timezone");
|
||||
const char *tz = NULL;
|
||||
|
||||
tz = switch_say_file_handle_get_variable(sh, "timezone");
|
||||
|
||||
if (say_args->type == SST_TIME_MEASUREMENT) {
|
||||
int64_t hours = 0;
|
||||
@@ -192,7 +181,7 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
|
||||
int64_t r = 0;
|
||||
|
||||
if (strchr(tosay, ':')) {
|
||||
char *tme = switch_core_session_strdup(session, tosay);
|
||||
char *tme = strdup(tosay);
|
||||
char *p;
|
||||
|
||||
if ((p = strrchr(tme, ':'))) {
|
||||
@@ -208,6 +197,7 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
|
||||
minutes = atoi(tme);
|
||||
}
|
||||
}
|
||||
free(tme);
|
||||
} else {
|
||||
if ((seconds = atol(tosay)) <= 0) {
|
||||
seconds = (int64_t) switch_epoch_time_now(NULL);
|
||||
@@ -227,39 +217,39 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
|
||||
}
|
||||
|
||||
if (hours) {
|
||||
say_num(hours, SSM_PRONOUNCED);
|
||||
say_num(sh, hours, SSM_PRONOUNCED);
|
||||
if (hours == 1) {
|
||||
say_file("time/hour.wav");
|
||||
switch_say_file(sh, "time/hour");
|
||||
} else {
|
||||
say_file("time/hours.wav");
|
||||
switch_say_file(sh, "time/hours");
|
||||
}
|
||||
} else {
|
||||
say_file("digits/0.wav");
|
||||
say_file("time/hours.wav");
|
||||
switch_say_file(sh, "digits/0");
|
||||
switch_say_file(sh, "time/hours");
|
||||
}
|
||||
|
||||
if (minutes) {
|
||||
say_num(minutes, SSM_PRONOUNCED);
|
||||
say_num(sh, minutes, SSM_PRONOUNCED);
|
||||
if (minutes == 1) {
|
||||
say_file("time/minute.wav");
|
||||
switch_say_file(sh, "time/minute");
|
||||
} else {
|
||||
say_file("time/minutes.wav");
|
||||
switch_say_file(sh, "time/minutes");
|
||||
}
|
||||
} else {
|
||||
say_file("digits/0.wav");
|
||||
say_file("time/minutes.wav");
|
||||
switch_say_file(sh, "digits/0");
|
||||
switch_say_file(sh, "time/minutes");
|
||||
}
|
||||
|
||||
if (seconds) {
|
||||
say_num(seconds, SSM_PRONOUNCED);
|
||||
say_num(sh, seconds, SSM_PRONOUNCED);
|
||||
if (seconds == 1) {
|
||||
say_file("time/second.wav");
|
||||
switch_say_file(sh, "time/second");
|
||||
} else {
|
||||
say_file("time/seconds.wav");
|
||||
switch_say_file(sh, "time/seconds");
|
||||
}
|
||||
} else {
|
||||
say_file("digits/0.wav");
|
||||
say_file("time/seconds.wav");
|
||||
switch_say_file(sh, "digits/0");
|
||||
switch_say_file(sh, "time/seconds");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -275,7 +265,7 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
|
||||
|
||||
if (tz) {
|
||||
int check = atoi(tz);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz);
|
||||
if (check) {
|
||||
switch_time_exp_tz(&tm, target, check);
|
||||
switch_time_exp_tz(&tm_now, target_now, check);
|
||||
@@ -329,13 +319,13 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
|
||||
}
|
||||
|
||||
if (say_today) {
|
||||
say_file("time/today.wav");
|
||||
switch_say_file(sh, "time/today");
|
||||
}
|
||||
if (say_yesterday) {
|
||||
say_file("time/yesterday.wav");
|
||||
switch_say_file(sh, "time/yesterday");
|
||||
}
|
||||
if (say_dow) {
|
||||
say_file("time/day-%d.wav", tm.tm_wday);
|
||||
switch_say_file(sh, "time/day-%d", tm.tm_wday);
|
||||
}
|
||||
|
||||
if (say_date) {
|
||||
@@ -344,20 +334,20 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
|
||||
}
|
||||
|
||||
if (say_month) {
|
||||
say_file("time/mon-%d.wav", tm.tm_mon);
|
||||
switch_say_file(sh, "time/mon-%d", tm.tm_mon);
|
||||
}
|
||||
if (say_day) {
|
||||
say_num(tm.tm_mday, SSM_COUNTED);
|
||||
say_num(sh, tm.tm_mday, SSM_COUNTED);
|
||||
}
|
||||
if (say_year) {
|
||||
say_num(tm.tm_year + 1900, SSM_PRONOUNCED);
|
||||
say_num(sh, tm.tm_year + 1900, SSM_PRONOUNCED);
|
||||
}
|
||||
|
||||
if (say_time) {
|
||||
int32_t hour = tm.tm_hour, pm = 0;
|
||||
|
||||
if (say_date || say_today || say_yesterday || say_dow) {
|
||||
say_file("time/at.wav");
|
||||
switch_say_file(sh, "time/at");
|
||||
}
|
||||
|
||||
if (hour > 12) {
|
||||
@@ -370,31 +360,31 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
|
||||
pm = 0;
|
||||
}
|
||||
|
||||
say_num(hour, SSM_PRONOUNCED);
|
||||
say_num(sh, hour, SSM_PRONOUNCED);
|
||||
|
||||
if (tm.tm_min > 9) {
|
||||
say_num(tm.tm_min, SSM_PRONOUNCED);
|
||||
say_num(sh, tm.tm_min, SSM_PRONOUNCED);
|
||||
} else if (tm.tm_min) {
|
||||
say_file("time/oh.wav");
|
||||
say_num(tm.tm_min, SSM_PRONOUNCED);
|
||||
switch_say_file(sh, "time/oh");
|
||||
say_num(sh, tm.tm_min, SSM_PRONOUNCED);
|
||||
} else {
|
||||
say_file("time/oclock.wav");
|
||||
switch_say_file(sh, "time/oclock");
|
||||
}
|
||||
|
||||
say_file("time/%s.wav", pm ? "p-m" : "a-m");
|
||||
switch_say_file(sh, "time/%s", pm ? "p-m" : "a-m");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t en_say_money(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
static switch_status_t en_say_money(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
char sbuf[16] = ""; /* enough for 999,999,999,999.99 (w/o the commas or leading $) */
|
||||
char *dollars = NULL;
|
||||
char *cents = NULL;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -415,43 +405,105 @@ static switch_status_t en_say_money(switch_core_session_t *session, char *tosay,
|
||||
|
||||
/* If negative say "negative" */
|
||||
if (sbuf[0] == '-') {
|
||||
say_file("currency/negative.wav");
|
||||
switch_say_file(sh, "currency/negative");
|
||||
dollars++;
|
||||
}
|
||||
|
||||
/* Say dollar amount */
|
||||
en_say_general_count(session, dollars, say_args, args);
|
||||
en_say_general_count(sh, dollars, say_args);
|
||||
if (atoi(dollars) == 1) {
|
||||
say_file("currency/dollar.wav");
|
||||
switch_say_file(sh, "currency/dollar");
|
||||
} else {
|
||||
say_file("currency/dollars.wav");
|
||||
switch_say_file(sh, "currency/dollars");
|
||||
}
|
||||
|
||||
/* Say "and" */
|
||||
say_file("currency/and.wav");
|
||||
|
||||
/* Say cents */
|
||||
if (cents) {
|
||||
en_say_general_count(session, cents, say_args, args);
|
||||
/* Say "and" */
|
||||
switch_say_file(sh, "currency/and");
|
||||
|
||||
en_say_general_count(sh, cents, say_args);
|
||||
if (atoi(cents) == 1) {
|
||||
say_file("currency/cent.wav");
|
||||
switch_say_file(sh, "currency/cent");
|
||||
} else {
|
||||
say_file("currency/cents.wav");
|
||||
switch_say_file(sh, "currency/cents");
|
||||
}
|
||||
} else {
|
||||
say_file("digits/0.wav");
|
||||
say_file("currency/cents.wav");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static switch_status_t en_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
static switch_status_t say_ip(switch_say_file_handle_t *sh,
|
||||
char *tosay,
|
||||
switch_say_args_t *say_args)
|
||||
|
||||
{
|
||||
char *a, *b, *c, *d;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
if (!(a = strdup(tosay))) {
|
||||
abort();
|
||||
}
|
||||
|
||||
switch_say_callback_t say_cb = NULL;
|
||||
if (!(b = strchr(a, '.'))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
*b++ = '\0';
|
||||
|
||||
if (!(c = strchr(b, '.'))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
*c++ = '\0';
|
||||
|
||||
if (!(d = strchr(c, '.'))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
*d++ = '\0';
|
||||
|
||||
say_num(sh, atoi(a), say_args->method);
|
||||
switch_say_file(sh, "digits/dot");
|
||||
say_num(sh, atoi(b), say_args->method);
|
||||
switch_say_file(sh, "digits/dot");
|
||||
say_num(sh, atoi(c), say_args->method);
|
||||
switch_say_file(sh, "digits/dot");
|
||||
say_num(sh, atoi(d), say_args->method);
|
||||
|
||||
end:
|
||||
|
||||
free(a);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t say_spell(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = tosay; p && *p; p++) {
|
||||
int a = tolower((int) *p);
|
||||
if (a >= '0' && a <= '9') {
|
||||
switch_say_file(sh, "digits/%c", a);
|
||||
} else {
|
||||
if (say_args->type == SST_NAME_SPELLED) {
|
||||
switch_say_file(sh, "ascii/%d", a);
|
||||
} else if (say_args->type == SST_NAME_PHONETIC) {
|
||||
switch_say_file(sh, "phonetic-ascii/%d", a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static switch_new_say_callback_t choose_callback(switch_say_args_t *say_args)
|
||||
{
|
||||
switch_new_say_callback_t say_cb = NULL;
|
||||
|
||||
switch (say_args->type) {
|
||||
case SST_NUMBER:
|
||||
@@ -468,11 +520,11 @@ static switch_status_t en_say(switch_core_session_t *session, char *tosay, switc
|
||||
say_cb = en_say_time;
|
||||
break;
|
||||
case SST_IP_ADDRESS:
|
||||
return switch_ivr_say_ip(session, tosay, en_say_general_count, say_args, args);
|
||||
say_cb = say_ip;
|
||||
break;
|
||||
case SST_NAME_SPELLED:
|
||||
case SST_NAME_PHONETIC:
|
||||
return switch_ivr_say_spell(session, tosay, say_args, args);
|
||||
say_cb = say_spell;
|
||||
break;
|
||||
case SST_CURRENCY:
|
||||
say_cb = en_say_money;
|
||||
@@ -482,11 +534,77 @@ static switch_status_t en_say(switch_core_session_t *session, char *tosay, switc
|
||||
break;
|
||||
}
|
||||
|
||||
if (say_cb) {
|
||||
return say_cb(session, tosay, say_args, args);
|
||||
return say_cb;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t run_callback(switch_new_say_callback_t say_cb, char *tosay, switch_say_args_t *say_args, switch_core_session_t *session, char **rstr)
|
||||
{
|
||||
switch_say_file_handle_t *sh;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_event_t *var_event = NULL;
|
||||
|
||||
if (session) {
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_channel_get_variables(channel, &var_event);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
switch_say_file_handle_create(&sh, say_args->ext, &var_event);
|
||||
|
||||
status = say_cb(sh, tosay, say_args);
|
||||
|
||||
if ((*rstr = switch_say_file_handle_detach_path(sh))) {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
switch_say_file_handle_destroy(&sh);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t en_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
{
|
||||
|
||||
switch_new_say_callback_t say_cb = NULL;
|
||||
char *string = NULL;
|
||||
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
say_cb = choose_callback(say_args);
|
||||
|
||||
if (say_cb) {
|
||||
status = run_callback(say_cb, tosay, say_args, session, &string);
|
||||
if (session && string) {
|
||||
status = switch_ivr_play_file(session, NULL, string, args);
|
||||
}
|
||||
|
||||
switch_safe_free(string);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t en_say_string(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, char **rstr)
|
||||
{
|
||||
|
||||
switch_new_say_callback_t say_cb = NULL;
|
||||
char *string = NULL;
|
||||
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
say_cb = choose_callback(say_args);
|
||||
|
||||
if (say_cb) {
|
||||
status = run_callback(say_cb, tosay, say_args, session, &string);
|
||||
if (string) {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
*rstr = string;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_say_en_load)
|
||||
@@ -497,7 +615,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_say_en_load)
|
||||
say_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_SAY_INTERFACE);
|
||||
say_interface->interface_name = "en";
|
||||
say_interface->say_function = en_say;
|
||||
|
||||
say_interface->say_string_function = en_say_string;
|
||||
|
||||
/* indicate that the module should continue to be loaded */
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -155,10 +155,23 @@ static switch_status_t es_say_general_count(switch_core_session_t *session, char
|
||||
int in;
|
||||
int x = 0;
|
||||
int places[9] = { 0 };
|
||||
char sbuf[13] = "";
|
||||
char sbuf[128] = "";
|
||||
switch_status_t status;
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -191,14 +204,6 @@ static switch_status_t es_say_general_count(switch_core_session_t *session, char
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
case SSM_ITERATED:
|
||||
{
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -362,7 +367,7 @@ static switch_status_t es_say_money(switch_core_session_t *session, char *tosay,
|
||||
char *dollars = NULL;
|
||||
char *cents = NULL;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
@@ -144,10 +144,27 @@ static switch_status_t fr_say_general_count(switch_core_session_t *session, char
|
||||
int in;
|
||||
int x = 0;
|
||||
int places[9] = { 0 };
|
||||
char sbuf[13] = "";
|
||||
char sbuf[128] = "";
|
||||
switch_status_t status;
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
if (*p == '1' && say_args->gender == SSG_FEMININE) {
|
||||
say_file("digits/%c_f.wav", *p);
|
||||
} else {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -175,18 +192,6 @@ static switch_status_t fr_say_general_count(switch_core_session_t *session, char
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
case SSM_ITERATED:
|
||||
{
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
if (*p == '1' && say_args->gender == SSG_FEMININE) {
|
||||
say_file("digits/%c_f.wav", *p);
|
||||
} else {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -399,7 +404,7 @@ static switch_status_t fr_say_money(switch_core_session_t *session, char *tosay,
|
||||
char *dollars = NULL;
|
||||
char *cents = NULL;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
File renamed without changes.
+4
-4
@@ -2,9 +2,9 @@
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="mod_file_string"
|
||||
ProjectGUID="{70564D74-199A-4452-9C60-19ED5F242F0D}"
|
||||
RootNamespace="mod_file_string"
|
||||
Name="mod_say_he"
|
||||
ProjectGUID="{0E1117D4-56BF-4B5F-926C-273FD99593DE}"
|
||||
RootNamespace="mod_say_he"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
@@ -274,7 +274,7 @@
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath=".\mod_file_string.c"
|
||||
RelativePath=".\mod_say_he.c"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
+9
-5
@@ -19,9 +19,9 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectName>mod_file_string</ProjectName>
|
||||
<ProjectGuid>{70564D74-199A-4452-9C60-19ED5F242F0D}</ProjectGuid>
|
||||
<RootNamespace>mod_file_string</RootNamespace>
|
||||
<ProjectName>mod_say_he</ProjectName>
|
||||
<ProjectGuid>{0E1117D4-56BF-4B5F-926C-273FD99593DE}</ProjectGuid>
|
||||
<RootNamespace>mod_say_he</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
@@ -117,9 +117,13 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="mod_file_string.c" />
|
||||
<ClCompile Include="mod_say_he.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\libs\win32\apr\libapr.2010.vcxproj">
|
||||
<Project>{f6c55d93-b927-4483-bb69-15aef3dd2dff}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
|
||||
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
@@ -128,4 +132,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -0,0 +1,866 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Shahar Hadas
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The Initial Developers of the Original Code are
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Michael B. Murdock <mike@mmurdock.org>
|
||||
* Marc O. Chouinard <mochouinard@moctel.com>
|
||||
* Yehavi Bourvine <yehavi@savion.huji.ac.il>
|
||||
* Eli Hayun <elihay@savion.huji.ac.il>
|
||||
* Portions created by the Initial Developers are Copyright (C)
|
||||
* the Initial Developers. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* mod_say_he.c -- Say for Hebrew
|
||||
*
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_say_he_load);
|
||||
SWITCH_MODULE_DEFINITION(mod_say_he, mod_say_he_load, NULL, NULL);
|
||||
|
||||
#define say_num(_sh, num, meth) { \
|
||||
char tmp[80]; \
|
||||
switch_status_t tstatus; \
|
||||
switch_say_method_t smeth = say_args->method; \
|
||||
switch_say_type_t stype = say_args->type; \
|
||||
say_args->type = SST_ITEMS; say_args->method = meth; \
|
||||
switch_snprintf(tmp, sizeof(tmp), "%u", (unsigned)num); \
|
||||
if ((tstatus = \
|
||||
he_say_general_count(_sh, tmp, say_args)) \
|
||||
!= SWITCH_STATUS_SUCCESS) { \
|
||||
return tstatus; \
|
||||
} \
|
||||
say_args->method = smeth; say_args->type = stype; \
|
||||
} \
|
||||
|
||||
|
||||
typedef enum {
|
||||
PGR_HUNDREDS = 1000,
|
||||
PGR_THOUSANDS = 100000,
|
||||
PGR_MILLIONS = 100000000,
|
||||
} play_group_range_t;
|
||||
|
||||
static switch_status_t play_group(switch_say_method_t method, switch_say_gender_t gender, int total, play_group_range_t range, int a, int b, int c, char *what, switch_say_file_handle_t *sh)
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "** total=[%d] range=[%d] a=[%d] b=[%d] c=[%d] gender=[%d] method=[%d] what=[%s]\n", total, range, a, b, c, gender, method, what);
|
||||
|
||||
/* Check for special cases of thousands */
|
||||
if (range == PGR_THOUSANDS && a == 0) {
|
||||
/* Check for special cases of 1000, 2000 ... 8000, 9000 */
|
||||
if (b == 0 && c != 0) {
|
||||
switch_say_file(sh, "digits/%d000", c);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Check for special case of 10,000 */
|
||||
if (b == 1 && c == 0) {
|
||||
switch_say_file(sh, "digits/10000");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for special case of million */
|
||||
if (range == PGR_MILLIONS && a == 0 && b == 0 && c == 1) {
|
||||
switch_say_file(sh, "digits/million");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Check for Hebrew SSM_COUNTED special case. Anything above 10 needs to said differently */
|
||||
if (method == SSM_COUNTED && range == PGR_HUNDREDS && total <= 10) {
|
||||
if (b) {
|
||||
switch_say_file(sh, "digits/h-10%s", gender == SSG_MASCULINE ? "_m" : "");
|
||||
} else {
|
||||
switch_say_file(sh, "digits/h-%d%s", c, gender == SSG_MASCULINE ? "_m" : "");
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* In Hebrew, hundreds can be said as "<number> hundreds", but the more correct
|
||||
* form of pronunciation required it to be recorded separately.
|
||||
* Note that hundreds are always pronounced in SSG_FEMININE form in hebrew, and were recorded as such.
|
||||
*/
|
||||
if (a) {
|
||||
switch_say_file(sh, "digits/%d00", a);
|
||||
}
|
||||
|
||||
if (b) {
|
||||
/* Check for two digits playback (10 to 19) */
|
||||
if (b > 1) {
|
||||
switch_say_file(sh, "digits/%d0", b);
|
||||
} else {
|
||||
if (range != PGR_HUNDREDS || gender == SSG_MASCULINE) {
|
||||
if ((range == PGR_MILLIONS && a) || (range != PGR_MILLIONS && total > 9)){ /* Check if need to say "and" */
|
||||
switch (c) {
|
||||
case 0:
|
||||
case 5:
|
||||
switch_say_file(sh, "digits/va");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
case 8:
|
||||
case 9:
|
||||
switch_say_file(sh, "digits/uu");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
switch_say_file(sh, "digits/ve");
|
||||
break;
|
||||
|
||||
default:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "play_group unkonwn digit (%d) Error! (SSG_MASCULINE)\n", c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch_say_file(sh, "digits/%d%d_m", b, c);
|
||||
} else {
|
||||
if ((range == PGR_MILLIONS && a) || (range != PGR_MILLIONS && total > 9)){ /* Check if need to say "and" */
|
||||
switch (c) {
|
||||
case 2:
|
||||
case 3:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
switch_say_file(sh, "digits/uu");
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
switch_say_file(sh, "digits/ve");
|
||||
break;
|
||||
|
||||
default:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "play_group unkonwn digit (%d) Error! (SSG_FEMININE)\n", c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch_say_file(sh, "digits/%d%d", b, c);
|
||||
}
|
||||
c = 0; /* Skip the pronunciation on the c value */
|
||||
}
|
||||
}
|
||||
|
||||
if (c) {
|
||||
if (range != PGR_HUNDREDS || gender == SSG_MASCULINE) {
|
||||
if ((range == PGR_MILLIONS && (b || a)) || (range != PGR_MILLIONS && total > 9)){ /* Check if need to say "and" */
|
||||
switch (c) {
|
||||
case 5:
|
||||
switch_say_file(sh, "digits/va");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
case 8:
|
||||
switch_say_file(sh, "digits/uu");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
case 9:
|
||||
switch_say_file(sh, "digits/ve");
|
||||
break;
|
||||
|
||||
default:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "play_group unkonwn digit (%d) Error! (SSG_MASCULINE)\n", c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch_say_file(sh, "digits/%d_m", c);
|
||||
} else {
|
||||
if ((range == PGR_MILLIONS && (b || a)) || (range != PGR_MILLIONS && total > 9)){ /* Check if need to say "and" */
|
||||
switch (c) {
|
||||
case 2:
|
||||
case 8:
|
||||
switch_say_file(sh, "digits/uu");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 9:
|
||||
switch_say_file(sh, "digits/ve");
|
||||
break;
|
||||
|
||||
default:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "play_group unkonwn digit (%d) Error! (SSG_FEMININE)\n", c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch_say_file(sh, "digits/%d", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (what && (a || b || c)) {
|
||||
switch_say_file(sh, what);
|
||||
}
|
||||
|
||||
/* Incase of SSM_COUNTED, in the case of total > 10, after the number was said, we need to say "be'mispar" (in number).
|
||||
* Although we shouldn't be here if total <= 10, I still preferred to have the criteria tested again. */
|
||||
if (method == SSM_COUNTED && range == PGR_HUNDREDS && total > 10) {
|
||||
switch_say_file(sh, "digits/in_number", c);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t he_say_general_count(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
int in, inCopy;
|
||||
int x = 0;
|
||||
int places[9] = { 0 };
|
||||
char sbuf[128] = "";
|
||||
switch_status_t status;
|
||||
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
if (*p != '0' && say_args->gender == SSG_MASCULINE) {
|
||||
switch_say_file(sh, "digits/%c_m", *p);
|
||||
} else {
|
||||
switch_say_file(sh, "digits/%c", *p);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
in = inCopy = atoi(tosay);
|
||||
|
||||
if (in != 0) {
|
||||
for (x = 8; x >= 0; x--) {
|
||||
int num = (int) pow(10, x);
|
||||
if ((places[(uint32_t) x] = in / num)) {
|
||||
in -= places[(uint32_t) x] * num;
|
||||
}
|
||||
}
|
||||
switch (say_args->method) {
|
||||
case SSM_COUNTED:
|
||||
/* TODO add 'ha' (the)? */
|
||||
case SSM_PRONOUNCED:
|
||||
if ((status = play_group(SSM_PRONOUNCED, say_args->gender, inCopy, PGR_MILLIONS, places[8], places[7], places[6], "digits/million", sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
if ((status = play_group(SSM_PRONOUNCED, say_args->gender, inCopy, PGR_THOUSANDS, places[5], places[4], places[3], "digits/thousand", sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
if ((status = play_group(say_args->method, say_args->gender, inCopy, PGR_HUNDREDS, places[2], places[1], places[0], NULL, sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch_say_file(sh, "digits/0");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t he_say_time(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
int32_t t;
|
||||
switch_time_t target = 0, target_now = 0;
|
||||
switch_time_exp_t tm, tm_now;
|
||||
uint8_t say_date = 0, say_time = 0, say_year = 0, say_month = 0, say_dow = 0, say_day = 0, say_yesterday = 0, say_today = 0;
|
||||
const char *tz = NULL;
|
||||
|
||||
tz = switch_say_file_handle_get_variable(sh, "timezone");
|
||||
|
||||
if (say_args->type == SST_TIME_MEASUREMENT) {
|
||||
int64_t hours = 0;
|
||||
int64_t minutes = 0;
|
||||
int64_t seconds = 0;
|
||||
int64_t r = 0;
|
||||
|
||||
if (strchr(tosay, ':')) {
|
||||
char *tme = strdup(tosay);
|
||||
char *p;
|
||||
|
||||
if ((p = strrchr(tme, ':'))) {
|
||||
*p++ = '\0';
|
||||
seconds = atoi(p);
|
||||
if ((p = strchr(tme, ':'))) {
|
||||
*p++ = '\0';
|
||||
minutes = atoi(p);
|
||||
if (tme) {
|
||||
hours = atoi(tme);
|
||||
}
|
||||
} else {
|
||||
minutes = atoi(tme);
|
||||
}
|
||||
}
|
||||
free(tme);
|
||||
} else {
|
||||
if ((seconds = atol(tosay)) <= 0) {
|
||||
seconds = (int64_t) switch_epoch_time_now(NULL);
|
||||
}
|
||||
|
||||
if (seconds >= 60) {
|
||||
minutes = seconds / 60;
|
||||
r = seconds % 60;
|
||||
seconds = r;
|
||||
}
|
||||
|
||||
if (minutes >= 60) {
|
||||
hours = minutes / 60;
|
||||
r = minutes % 60;
|
||||
minutes = r;
|
||||
}
|
||||
}
|
||||
|
||||
say_args->gender = SSG_FEMININE;
|
||||
|
||||
if (hours) {
|
||||
switch_say_file(sh, "time/hour");
|
||||
say_num(sh, hours, SSM_PRONOUNCED);
|
||||
} else {
|
||||
switch_say_file(sh, "digits/0");
|
||||
switch_say_file(sh, "time/hours");
|
||||
}
|
||||
|
||||
if (minutes) {
|
||||
if (minutes == 1) {
|
||||
switch_say_file(sh, "time/minute");
|
||||
say_num(sh, minutes, SSM_PRONOUNCED);
|
||||
} else {
|
||||
say_num(sh, minutes, SSM_PRONOUNCED);
|
||||
switch_say_file(sh, "time/minutes");
|
||||
}
|
||||
} else {
|
||||
switch_say_file(sh, "digits/0");
|
||||
switch_say_file(sh, "time/minutes");
|
||||
}
|
||||
|
||||
if (seconds) {
|
||||
if (seconds == 1) {
|
||||
switch_say_file(sh, "time/second");
|
||||
say_num(sh, seconds, SSM_PRONOUNCED);
|
||||
} else {
|
||||
say_num(sh, seconds, SSM_PRONOUNCED);
|
||||
switch_say_file(sh, "time/seconds");
|
||||
}
|
||||
} else {
|
||||
switch_say_file(sh, "digits/0");
|
||||
switch_say_file(sh, "time/seconds");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if ((t = atol(tosay)) > 0) {
|
||||
target = switch_time_make(t, 0);
|
||||
target_now = switch_micro_time_now();
|
||||
} else {
|
||||
target = switch_micro_time_now();
|
||||
target_now = switch_micro_time_now();
|
||||
}
|
||||
|
||||
if (tz) {
|
||||
int check = atoi(tz);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz);
|
||||
if (check) {
|
||||
switch_time_exp_tz(&tm, target, check);
|
||||
switch_time_exp_tz(&tm_now, target_now, check);
|
||||
} else {
|
||||
switch_time_exp_tz_name(tz, &tm, target);
|
||||
switch_time_exp_tz_name(tz, &tm_now, target_now);
|
||||
}
|
||||
} else {
|
||||
switch_time_exp_lt(&tm, target);
|
||||
switch_time_exp_lt(&tm_now, target_now);
|
||||
}
|
||||
|
||||
switch (say_args->type) {
|
||||
case SST_CURRENT_DATE_TIME:
|
||||
say_date = say_time = 1;
|
||||
break;
|
||||
case SST_CURRENT_DATE:
|
||||
say_date = 1;
|
||||
break;
|
||||
case SST_CURRENT_TIME:
|
||||
say_time = 1;
|
||||
break;
|
||||
case SST_SHORT_DATE_TIME:
|
||||
say_time = 1;
|
||||
if (tm.tm_year != tm_now.tm_year) {
|
||||
say_date = 1;
|
||||
break;
|
||||
}
|
||||
if (tm.tm_yday == tm_now.tm_yday) {
|
||||
say_today = 1;
|
||||
break;
|
||||
}
|
||||
if (tm.tm_yday == tm_now.tm_yday - 1) {
|
||||
say_yesterday = 1;
|
||||
break;
|
||||
}
|
||||
if (tm.tm_yday >= tm_now.tm_yday - 5) {
|
||||
say_dow = 1;
|
||||
break;
|
||||
}
|
||||
if (tm.tm_mon != tm_now.tm_mon) {
|
||||
say_month = say_day = say_dow = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
say_month = say_day = say_dow = 1;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (say_today) {
|
||||
switch_say_file(sh, "time/today");
|
||||
}
|
||||
if (say_yesterday) {
|
||||
switch_say_file(sh, "time/yesterday");
|
||||
}
|
||||
if (say_dow) {
|
||||
switch_say_file(sh, "time/day-%d", tm.tm_wday);
|
||||
}
|
||||
|
||||
if (say_date) {
|
||||
say_year = say_month = say_day = say_dow = 1;
|
||||
say_today = say_yesterday = 0;
|
||||
}
|
||||
|
||||
/* In Hebrew it's costumed to speak the day before the month. */
|
||||
if (say_day) {
|
||||
say_args->gender = SSG_MASCULINE;
|
||||
say_num(sh, tm.tm_mday, SSM_PRONOUNCED);
|
||||
}
|
||||
if (say_month) {
|
||||
switch_say_file(sh, "time/at");
|
||||
switch_say_file(sh, "time/mon-%d", tm.tm_mon);
|
||||
}
|
||||
if (say_year) {
|
||||
say_args->gender = SSG_FEMININE;
|
||||
say_num(sh, tm.tm_year + 1900, SSM_PRONOUNCED);
|
||||
}
|
||||
|
||||
if (say_time) {
|
||||
int32_t hour = tm.tm_hour, pm = 0;
|
||||
|
||||
if (say_date || say_today || say_yesterday || say_dow) {
|
||||
switch_say_file(sh, "time/at-hour");
|
||||
}
|
||||
else {
|
||||
switch_say_file(sh, "time/hour");
|
||||
}
|
||||
|
||||
if (hour > 12) {
|
||||
hour -= 12;
|
||||
pm = 1;
|
||||
} else if (hour == 12) {
|
||||
pm = 1;
|
||||
} else if (hour == 0) {
|
||||
hour = 12;
|
||||
pm = 0;
|
||||
}
|
||||
|
||||
say_args->gender = SSG_FEMININE;
|
||||
say_num(sh, hour, SSM_PRONOUNCED);
|
||||
|
||||
if (tm.tm_min) {
|
||||
switch (tm.tm_min) {
|
||||
case 2:
|
||||
case 8:
|
||||
case 12:
|
||||
case 13:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 30:
|
||||
switch_say_file(sh, "digits/uu");
|
||||
break;
|
||||
|
||||
case 50:
|
||||
switch_say_file(sh, "digits/va");
|
||||
break;
|
||||
|
||||
default:
|
||||
switch_say_file(sh, "digits/ve");
|
||||
break;
|
||||
}
|
||||
|
||||
if (tm.tm_min == 1) {
|
||||
switch_say_file(sh, "time/minute");
|
||||
switch_say_file(sh, "digits/1");
|
||||
} else {
|
||||
say_num(sh, tm.tm_min, SSM_PRONOUNCED);
|
||||
switch_say_file(sh, "time/minutes");
|
||||
}
|
||||
}
|
||||
|
||||
switch_say_file(sh, "time/%s", pm ? "p-m" : "a-m");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t he_say_money(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
char sbuf[16] = ""; /* enough for 999,999,999,999.99 (w/o the commas or leading $) */
|
||||
char *currency = NULL;
|
||||
char *cents = NULL;
|
||||
int icents = 0;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
currency = sbuf;
|
||||
|
||||
if ((cents = strchr(sbuf, '.'))) {
|
||||
*cents++ = '\0';
|
||||
if (strlen(cents) > 2) {
|
||||
cents[2] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* If positive sign - skip over" */
|
||||
if (sbuf[0] == '+') {
|
||||
++currency;
|
||||
}
|
||||
|
||||
/* If negative say "negative" */
|
||||
if (sbuf[0] == '-') {
|
||||
switch_say_file(sh, "currency/negative");
|
||||
++currency;
|
||||
}
|
||||
|
||||
/* Say shekel amount (Israel currency) */
|
||||
switch (atoi(currency)) {
|
||||
case 1:
|
||||
switch_say_file(sh, "currency/shekel");
|
||||
switch_say_file(sh, "digits/1_m");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* In the case of 2, because currency, we need a special case of 2 pronunciation */
|
||||
switch_say_file(sh, "digits/shney");
|
||||
switch_say_file(sh, "currency/shkalim");
|
||||
break;
|
||||
|
||||
default:
|
||||
say_args->gender = SSG_MASCULINE;
|
||||
he_say_general_count(sh, currency, say_args);
|
||||
switch_say_file(sh, "currency/shkalim");
|
||||
break;
|
||||
}
|
||||
|
||||
if (cents) {
|
||||
/* We need to use the value twice, so speed it up by atoi only once */
|
||||
icents = atoi(cents);
|
||||
|
||||
/* Say "and" */
|
||||
switch (icents) {
|
||||
case 2:
|
||||
case 8:
|
||||
case 12:
|
||||
case 13:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 30:
|
||||
case 80:
|
||||
switch_say_file(sh, "digits/uu");
|
||||
break;
|
||||
|
||||
case 50:
|
||||
switch_say_file(sh, "digits/va");
|
||||
break;
|
||||
|
||||
default:
|
||||
switch_say_file(sh, "digits/ve");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Say agorot (Israel currency equivalent for "cents") */
|
||||
switch (icents) {
|
||||
case 0:
|
||||
switch_say_file(sh, "digits/0");
|
||||
switch_say_file(sh, "currency/agorot");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
switch_say_file(sh, "currency/agora");
|
||||
switch_say_file(sh, "digits/1");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* In the case of 2, because currency, we need a special case of 2 pronunciation */
|
||||
switch_say_file(sh, "digits/shtey");
|
||||
switch_say_file(sh, "currency/agorot");
|
||||
break;
|
||||
|
||||
default:
|
||||
say_args->gender = SSG_FEMININE;
|
||||
he_say_general_count(sh, cents, say_args);
|
||||
switch_say_file(sh, "currency/agorot");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t say_ip(switch_say_file_handle_t *sh,
|
||||
char *tosay,
|
||||
switch_say_args_t *say_args)
|
||||
|
||||
{
|
||||
char *a, *b, *c, *d;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
if (!(a = strdup(tosay))) {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!(b = strchr(a, '.'))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
*b++ = '\0';
|
||||
|
||||
if (!(c = strchr(b, '.'))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
*c++ = '\0';
|
||||
|
||||
if (!(d = strchr(c, '.'))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
*d++ = '\0';
|
||||
|
||||
say_num(sh, atoi(a), say_args->method);
|
||||
switch_say_file(sh, "digits/dot");
|
||||
say_num(sh, atoi(b), say_args->method);
|
||||
switch_say_file(sh, "digits/dot");
|
||||
say_num(sh, atoi(c), say_args->method);
|
||||
switch_say_file(sh, "digits/dot");
|
||||
say_num(sh, atoi(d), say_args->method);
|
||||
|
||||
end:
|
||||
|
||||
free(a);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t say_spell(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = tosay; p && *p; p++) {
|
||||
int a = tolower((int) *p);
|
||||
if (a >= '0' && a <= '9') {
|
||||
if (a != '0' && say_args->gender == SSG_MASCULINE) {
|
||||
switch_say_file(sh, "digits/%c_m", a);
|
||||
} else {
|
||||
switch_say_file(sh, "digits/%c", a);
|
||||
}
|
||||
} else {
|
||||
if (say_args->type == SST_NAME_SPELLED) {
|
||||
switch_say_file(sh, "ascii/%d", a);
|
||||
} else if (say_args->type == SST_NAME_PHONETIC) {
|
||||
switch_say_file(sh, "phonetic-ascii/%d", a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_new_say_callback_t choose_callback(switch_say_args_t *say_args)
|
||||
{
|
||||
switch_new_say_callback_t say_cb = NULL;
|
||||
|
||||
switch (say_args->type) {
|
||||
case SST_NUMBER:
|
||||
case SST_ITEMS:
|
||||
case SST_PERSONS:
|
||||
case SST_MESSAGES:
|
||||
say_cb = he_say_general_count;
|
||||
break;
|
||||
case SST_TIME_MEASUREMENT:
|
||||
case SST_CURRENT_DATE:
|
||||
case SST_CURRENT_TIME:
|
||||
case SST_CURRENT_DATE_TIME:
|
||||
case SST_SHORT_DATE_TIME:
|
||||
say_cb = he_say_time;
|
||||
break;
|
||||
case SST_IP_ADDRESS:
|
||||
say_cb = say_ip;
|
||||
break;
|
||||
case SST_NAME_SPELLED:
|
||||
case SST_NAME_PHONETIC:
|
||||
say_cb = say_spell;
|
||||
break;
|
||||
case SST_CURRENCY:
|
||||
say_cb = he_say_money;
|
||||
break;
|
||||
default:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown Say type=[%d]\n", say_args->type);
|
||||
break;
|
||||
}
|
||||
|
||||
return say_cb;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t run_callback(switch_new_say_callback_t say_cb, char *tosay, switch_say_args_t *say_args, switch_core_session_t *session, char **rstr)
|
||||
{
|
||||
switch_say_file_handle_t *sh;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_event_t *var_event = NULL;
|
||||
|
||||
if (session) {
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_channel_get_variables(channel, &var_event);
|
||||
}
|
||||
|
||||
switch_say_file_handle_create(&sh, say_args->ext, &var_event);
|
||||
|
||||
status = say_cb(sh, tosay, say_args);
|
||||
|
||||
if ((*rstr = switch_say_file_handle_detach_path(sh))) {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
switch_say_file_handle_destroy(&sh);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t he_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
{
|
||||
|
||||
switch_new_say_callback_t say_cb = NULL;
|
||||
char *string = NULL;
|
||||
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
say_cb = choose_callback(say_args);
|
||||
|
||||
if (say_cb) {
|
||||
status = run_callback(say_cb, tosay, say_args, session, &string);
|
||||
if (session && string) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "** he_say [%s]\n", string);
|
||||
status = switch_ivr_play_file(session, NULL, string, args);
|
||||
}
|
||||
|
||||
switch_safe_free(string);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t he_say_string(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, char **rstr)
|
||||
{
|
||||
|
||||
switch_new_say_callback_t say_cb = NULL;
|
||||
char *string = NULL;
|
||||
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
say_cb = choose_callback(say_args);
|
||||
|
||||
if (say_cb) {
|
||||
status = run_callback(say_cb, tosay, say_args, session, &string);
|
||||
if (string) {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
*rstr = string;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_say_he_load)
|
||||
{
|
||||
switch_say_interface_t *say_interface;
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
say_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_SAY_INTERFACE);
|
||||
say_interface->interface_name = "he";
|
||||
say_interface->say_function = he_say;
|
||||
say_interface->say_string_function = he_say_string;
|
||||
|
||||
/* indicate that the module should continue to be loaded */
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
+4
-4
@@ -2,9 +2,9 @@
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="mod_file_string"
|
||||
ProjectGUID="{2CA40887-1622-46A1-A7F9-17FD7E7E545B}"
|
||||
RootNamespace="mod_file_string"
|
||||
Name="mod_say_he"
|
||||
ProjectGUID="{0E1117D4-56BF-4B5F-926C-273FD99593DE}"
|
||||
RootNamespace="mod_say_he"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
@@ -42,7 +42,7 @@
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath=".\mod_file_string.c"
|
||||
RelativePath=".\mod_say_he.c"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
@@ -232,7 +232,7 @@ static switch_status_t hr_say_count(switch_core_session_t *session, char* gen,
|
||||
|
||||
strcpy(tgen, gen);
|
||||
|
||||
if (!(tosay = strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
if (!(tosay = strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -356,10 +356,23 @@ static switch_status_t hr_say_general_count(switch_core_session_t *session, char
|
||||
int in;
|
||||
int x = 0;
|
||||
int places[9] = { 0 };
|
||||
char sbuf[13] = "";
|
||||
char sbuf[128] = "";
|
||||
int number;
|
||||
switch_status_t status;
|
||||
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
@@ -391,14 +404,6 @@ static switch_status_t hr_say_general_count(switch_core_session_t *session, char
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
case SSM_ITERATED:
|
||||
{
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1016,7 +1021,7 @@ static switch_status_t hr_say_money(switch_core_session_t *session, char *tosay,
|
||||
int zadnja_lipa = 0;
|
||||
int predzadnja_lipa = 0;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = strip_nonnumerics(tosay, sbuf, sizeof(sbuf))))
|
||||
if (strlen(tosay) > 15 || !(tosay = strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1)))
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
|
||||
@@ -122,11 +122,24 @@ static switch_status_t hu_say_general_count(switch_core_session_t *session, char
|
||||
int in;
|
||||
int x = 0;
|
||||
int places[9] = { 0 };
|
||||
char sbuf[13] = "";
|
||||
char sbuf[128] = "";
|
||||
int number;
|
||||
switch_status_t status;
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -157,14 +170,6 @@ static switch_status_t hu_say_general_count(switch_core_session_t *session, char
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
case SSM_ITERATED:
|
||||
{
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -356,7 +361,7 @@ static switch_status_t hu_say_money(switch_core_session_t *session, char *tosay,
|
||||
char sbuf[16] = "";
|
||||
char *forint;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
@@ -131,10 +131,23 @@ static switch_status_t it_say_general_count(switch_core_session_t *session, char
|
||||
int in;
|
||||
int places_count = 0;
|
||||
int places[9] = { 0 };
|
||||
char sbuf[13] = "";
|
||||
char sbuf[128] = "";
|
||||
switch_status_t status;
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -202,14 +215,6 @@ static switch_status_t it_say_general_count(switch_core_session_t *session, char
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
case SSM_ITERATED:
|
||||
{
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -355,7 +360,7 @@ static switch_status_t it_say_money(switch_core_session_t *session, char *tosay,
|
||||
char *dollars = NULL;
|
||||
char *cents = NULL;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
@@ -84,11 +84,24 @@ SWITCH_MODULE_DEFINITION(mod_say_ja, mod_say_ja_load, NULL, NULL);
|
||||
static switch_status_t ja_say_general_count(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
{
|
||||
int in;
|
||||
char sbuf[13] = "";
|
||||
char sbuf[128] = "";
|
||||
char digits[11];
|
||||
int i;
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -218,13 +231,6 @@ static switch_status_t ja_say_general_count(switch_core_session_t *session, char
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSM_ITERATED:
|
||||
{
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++)
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -398,7 +404,7 @@ static switch_status_t ja_say_money(switch_core_session_t *session, char *tosay,
|
||||
char *dollars = NULL;
|
||||
char *cents = NULL;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
@@ -118,10 +118,23 @@ static switch_status_t nl_say_general_count(switch_core_session_t *session, char
|
||||
int in;
|
||||
int x = 0;
|
||||
int places[9] = { 0 };
|
||||
char sbuf[13] = "";
|
||||
char sbuf[128] = "";
|
||||
switch_status_t status;
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -149,14 +162,6 @@ static switch_status_t nl_say_general_count(switch_core_session_t *session, char
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
case SSM_ITERATED:
|
||||
{
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -319,7 +324,7 @@ static switch_status_t nl_say_money(switch_core_session_t *session, char *tosay,
|
||||
char *dollars = NULL;
|
||||
char *cents = NULL;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ static switch_status_t pt_say_general_count(switch_core_session_t *session, char
|
||||
switch_status_t status;
|
||||
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
@@ -166,7 +166,7 @@ static switch_status_t pt_say_general_count(switch_core_session_t *session, char
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -428,7 +428,7 @@ static switch_status_t pt_say_money(switch_core_session_t *session, char *tosay,
|
||||
char *dollars = NULL;
|
||||
char *cents = NULL;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
+343
-152
@@ -58,63 +58,57 @@ struct say_t matrix[7][8] = { {m_00, m_01, m_02, m_03, m_04, m_05, m_06, m_07},
|
||||
{m_60, m_61, m_62, m_63, m_64, m_65, m_66, m_67}
|
||||
};
|
||||
|
||||
|
||||
struct say_cur_t matrix_currency[3] = {c_0, c_1, c_2};
|
||||
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_say_ru_load);
|
||||
SWITCH_MODULE_DEFINITION(mod_say_ru, mod_say_ru_load, NULL, NULL);
|
||||
|
||||
#define say_file(...) {\
|
||||
char tmp[80];\
|
||||
switch_status_t tstatus;\
|
||||
switch_snprintf(tmp, sizeof(tmp), __VA_ARGS__);\
|
||||
if ((tstatus = switch_ivr_play_file(session, NULL, tmp, args)) != SWITCH_STATUS_SUCCESS){ \
|
||||
return tstatus;\
|
||||
}\
|
||||
if (!switch_channel_ready(switch_core_session_get_channel(session))) {\
|
||||
return SWITCH_STATUS_FALSE;\
|
||||
}}
|
||||
|
||||
static switch_status_t play_group(say_type_t say_type, casus_t casus, int a, int b, int c,
|
||||
unit_t what, switch_core_session_t *session, switch_input_args_t *args)
|
||||
static switch_status_t play_group(say_gender_t gender, cases_t cases, int a, int b, int c, unit_t what, switch_say_file_handle_t *sh)
|
||||
{
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play_group ! %d%d%d gender=%d causes=%d\n",a,b,c,gender,cases);
|
||||
if (a) {
|
||||
if (((b == 0) && (c == 0)) || (matrix[casus][say_type].all == 1)) { //если b и с равны 0 то сказать шестьсот, сестисотый, шестисотая
|
||||
if (((b == 0) && (c == 0)) || (matrix[cases][gender].all == 1)) { //если b и с равны 0 то сказать шестьсот, сестисотый, шестисотая
|
||||
if (what == million) { //префикс число окончание
|
||||
say_file("digits/%s%d00%s.wav", matrix[casus][say_type].million[12], a, matrix[casus][say_type].million[13]);
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].million[11]);
|
||||
switch_say_file(sh, "digits/%s%d00%s", matrix[cases][gender].million[12], a, matrix[cases][gender].million[13]);
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].million[11]);
|
||||
} else if (what == thousand) {
|
||||
say_file("digits/%s%d00%s.wav", matrix[casus][say_type].thousand[12], a, matrix[casus][say_type].thousand[13]);
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].thousand[11]);
|
||||
switch_say_file(sh, "digits/%s%d00%s", matrix[cases][gender].thousand[12], a, matrix[cases][gender].thousand[13]);
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].thousand[11]);
|
||||
} else {
|
||||
say_file("digits/%s%d00%s.wav", matrix[casus][say_type].num[6], a, matrix[casus][say_type].num[7]);
|
||||
switch_say_file(sh, "digits/%s%d00%s", matrix[cases][gender].num[6], a, matrix[cases][gender].num[7]);
|
||||
}
|
||||
} else { //если дальше есть цифры то тысячи и миллионы не прозносить пока
|
||||
say_file("digits/%d00.wav", a);
|
||||
switch_say_file(sh, "digits/%d00", a);
|
||||
}
|
||||
}
|
||||
|
||||
if (b) {
|
||||
if (b > 1) { //если 20 и больше
|
||||
if ((c == 0) || (matrix[casus][say_type].all == 1)) { //если с равны 0 то сказать 20, двадцати, двадцатая
|
||||
if ((c == 0) || (matrix[cases][gender].all == 1)) { //если с равны 0 то сказать 20, двадцати, двадцатая
|
||||
if (what == million) { //префикс число окончание
|
||||
say_file("digits/%s%d0%s.wav", matrix[casus][say_type].million[12], b, matrix[casus][say_type].million[13]);
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].million[11]);
|
||||
switch_say_file(sh, "digits/%s%d0%s", matrix[cases][gender].million[12], b, matrix[cases][gender].million[13]);
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].million[11]);
|
||||
} else if (what == thousand) {
|
||||
say_file("digits/%s%d0%s.wav", matrix[casus][say_type].thousand[12], b, matrix[casus][say_type].thousand[13]);
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].thousand[11]);
|
||||
switch_say_file(sh, "digits/%s%d0%s", matrix[cases][gender].thousand[12], b, matrix[cases][gender].thousand[13]);
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].thousand[11]);
|
||||
} else {
|
||||
say_file("digits/%s%d0%s.wav", matrix[casus][say_type].num[6], b, matrix[casus][say_type].num[7]);
|
||||
switch_say_file(sh, "digits/%s%d0%s", matrix[cases][gender].num[6], b, matrix[cases][gender].num[7]);
|
||||
}
|
||||
} else { //если есть дальше цифры
|
||||
say_file("digits/%d0.wav", b);
|
||||
switch_say_file(sh, "digits/%d0", b);
|
||||
}
|
||||
} else { //от 10 до 19
|
||||
if (what == million) {
|
||||
say_file("digits/%s%d%d%s.wav", matrix[casus][say_type].million[12], b, c, matrix[casus][say_type].million[13]);
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].million[11]);
|
||||
switch_say_file(sh, "digits/%s%d%d%s", matrix[cases][gender].million[12], b, c, matrix[cases][gender].million[13]);
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].million[11]);
|
||||
} else if (what == thousand) {
|
||||
say_file("digits/%s%d%d%s.wav", matrix[casus][say_type].thousand[12], b, c, matrix[casus][say_type].thousand[13]);
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].thousand[11]);
|
||||
switch_say_file(sh, "digits/%s%d%d%s", matrix[cases][gender].thousand[12], b, c, matrix[cases][gender].thousand[13]);
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].thousand[11]);
|
||||
} else { //просто произнести цифры с префиксом и окончанием
|
||||
say_file("digits/%s%d%d%s.wav", matrix[casus][say_type].num[6], b, c, matrix[casus][say_type].num[7]);
|
||||
switch_say_file(sh, "digits/%s%d%d%s", matrix[cases][gender].num[6], b, c, matrix[cases][gender].num[7]);
|
||||
}
|
||||
c = 0;
|
||||
}
|
||||
@@ -123,28 +117,28 @@ static switch_status_t play_group(say_type_t say_type, casus_t casus, int a, int
|
||||
if (c || what == zero) {
|
||||
if (c <= 5) {
|
||||
if (what == million) {
|
||||
if ((strlen(matrix[casus][say_type].million[c * 2])) > 0) { // не произносить если не заданно например 1 миллион а просто миллион
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].million[c * 2])
|
||||
if ((strlen(matrix[cases][gender].million[c * 2])) > 0) { // не произносить если не заданно например 1 миллион а просто миллион
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].million[c * 2]);
|
||||
}
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].million[c * 2 + 1]);
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].million[c * 2 + 1]);
|
||||
} else if (what == thousand) {
|
||||
if ((strlen(matrix[casus][say_type].thousand[c * 2])) > 0) { // не произносить если не заданно например одна тысячас а просто тысяча
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].thousand[c * 2])
|
||||
if ((strlen(matrix[cases][gender].thousand[c * 2])) > 0) { // не произносить если не заданно например одна тысячас а просто тысяча
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].thousand[c * 2]);
|
||||
}
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].thousand[c * 2 + 1]);
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].thousand[c * 2 + 1]);
|
||||
} else { //просто произнести цифры с префиксом и окончанием
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].num[c]);
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].num[c]);
|
||||
}
|
||||
} else { /* больше 5 */
|
||||
|
||||
if (what == million) {
|
||||
say_file("digits/%s%d%s.wav", matrix[casus][say_type].million[12], c, matrix[casus][say_type].million[13]);
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].million[11]);
|
||||
switch_say_file(sh, "digits/%s%d%s", matrix[cases][gender].million[12], c, matrix[cases][gender].million[13]);
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].million[11]);
|
||||
} else if (what == thousand) {
|
||||
say_file("digits/%s%d%s.wav", matrix[casus][say_type].thousand[12], c, matrix[casus][say_type].thousand[13]);
|
||||
say_file("digits/%s.wav", matrix[casus][say_type].thousand[11]);
|
||||
switch_say_file(sh, "digits/%s%d%s", matrix[cases][gender].thousand[12], c, matrix[cases][gender].thousand[13]);
|
||||
switch_say_file(sh, "digits/%s", matrix[cases][gender].thousand[11]);
|
||||
} else { //просто произнести цифры с префиксом и окончанием
|
||||
say_file("digits/%s%d%s.wav", matrix[casus][say_type].num[6], c, matrix[casus][say_type].num[7]);
|
||||
switch_say_file(sh, "digits/%s%d%s", matrix[cases][gender].num[6], c, matrix[cases][gender].num[7]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,7 +146,7 @@ static switch_status_t play_group(say_type_t say_type, casus_t casus, int a, int
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t ru_say_count(switch_core_session_t *session, char *tosay, say_type_t say_type, casus_t casus, switch_input_args_t *args)
|
||||
static switch_status_t ru_say_count(switch_say_file_handle_t *sh, char *tosay, say_gender_t gender, cases_t cases)
|
||||
{
|
||||
int in;
|
||||
int x = 0;
|
||||
@@ -162,10 +156,10 @@ static switch_status_t ru_say_count(switch_core_session_t *session, char *tosay,
|
||||
|
||||
switch_status_t status;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say_count %s!\n", tosay);
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say_count %s! gender=%d causes=%d\n", tosay,gender,cases);
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
@@ -182,44 +176,40 @@ static switch_status_t ru_say_count(switch_core_session_t *session, char *tosay,
|
||||
|
||||
//миллионы
|
||||
if (places[8] || places[7] || places[6]) {
|
||||
if ((in_ % 1000000 > 0) && (matrix[casus][say_type].all != 1)) { // если поле миллионов есть цифры поизнести как числительое именительного падежа
|
||||
if ((status = play_group(male_c, nominativus, places[8], places[7], places[6], million, session, args)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d million! status=%d\n", places[8], places[7], places[6],
|
||||
status);
|
||||
if ((in_ % 1000000 > 0) && (matrix[cases][gender].all != 1)) { // если поле миллионов есть цифры поизнести как числительое именительного падежа
|
||||
if ((status = play_group(male, nominativus, places[8], places[7], places[6], million, sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d million! status=%d\n", places[8], places[7], places[6], status);
|
||||
return status;
|
||||
}
|
||||
} else { // иначе произнести в нужном падеже
|
||||
if ((status = play_group(say_type, casus, places[8], places[7], places[6], million, session, args)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d million! status=%d\n", places[8], places[7], places[6],
|
||||
status);
|
||||
if ((status = play_group(gender, cases, places[8], places[7], places[6], million, sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d million! status=%d\n", places[8], places[7], places[6], status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
//тысячи
|
||||
if (places[5] || places[4] || places[3]) {
|
||||
if ((in_ % 1000 > 0) && (matrix[casus][say_type].all != 1)) { // если поле миллионов есть цифры поизнести как числительое именительного падежа
|
||||
if ((status = play_group(male_c, nominativus, places[5], places[4], places[3], thousand, session, args)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d thousand! status=%d\n", places[5], places[4], places[3],
|
||||
status);
|
||||
if ((in_ % 1000 > 0) && (matrix[cases][gender].all != 1)) { // если поле миллионов есть цифры поизнести как числительое именительного падежа
|
||||
if ((status = play_group(male, nominativus, places[5], places[4], places[3], thousand, sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d thousand! status=%d\n", places[5], places[4], places[3], status);
|
||||
return status;
|
||||
}
|
||||
} else { // иначе произнести в нужном падеже
|
||||
if ((status = play_group(say_type, casus, places[5], places[4], places[3], thousand, session, args)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d thousand! status=%d\n", places[5], places[4], places[3],
|
||||
status);
|
||||
if ((status = play_group(gender, cases, places[5], places[4], places[3], thousand, sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d thousand! status=%d\n", places[5], places[4], places[3], status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
// сотни
|
||||
if ((status = play_group(say_type, casus, places[2], places[1], places[0], empty, session, args)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d thousand! status=%d\n", places[5], places[4], places[3], status);
|
||||
if ((status = play_group(gender, cases, places[2], places[1], places[0], empty, sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d thousand! status=%d\n", places[5], places[4], places[3], status);
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
if ((status = play_group(say_type, casus, places[2], places[1], places[0], zero, session, args)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d other!\n", places[2], places[1], places[0]);
|
||||
if ((status = play_group(gender, cases, places[2], places[1], places[0], zero, sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d other!\n", places[2], places[1], places[0]);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
@@ -228,28 +218,37 @@ static switch_status_t ru_say_count(switch_core_session_t *session, char *tosay,
|
||||
}
|
||||
|
||||
//дописать
|
||||
static switch_status_t ru_say_general_count(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
static switch_status_t ru_say_general_count(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args,say_opt_t *say_opt)
|
||||
{
|
||||
switch_status_t status;
|
||||
casus_t casus; //падеж
|
||||
say_type_t say_type; //тип произношения
|
||||
cases_t cases; //падеж
|
||||
say_gender_t gender; //тип произношения
|
||||
|
||||
switch (say_args->type) {
|
||||
case SST_MESSAGES:
|
||||
say_type = it_c;
|
||||
casus = nominativus;
|
||||
gender = it;
|
||||
cases = nominativus;
|
||||
break;
|
||||
default:
|
||||
say_type = male_c;
|
||||
casus = nominativus;
|
||||
gender = male;
|
||||
cases = nominativus;
|
||||
if (say_opt->gender>0) {
|
||||
gender=say_opt->gender;
|
||||
// //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " opt_gender=%d type=%d cases=%d\n", gender, cases,say_opt->gender);
|
||||
}
|
||||
if (say_opt->cases>0) {
|
||||
cases=say_opt->cases;
|
||||
// //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " opt_gender=%d type=%d cases=%d\n", gender, cases,say_opt->gender);
|
||||
|
||||
}
|
||||
break;
|
||||
};
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " type=%d casus=%d\n", say_type, casus);
|
||||
status = ru_say_count(session, tosay, say_type, casus, args);
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " opt_gender=%d type=%d cases=%d\n", gender, cases,say_opt->gender);
|
||||
status = ru_say_count(sh, tosay, (say_gender_t)gender, (cases_t)cases);
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t ru_say_money(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
static switch_status_t ru_say_money(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args,say_opt_t *say_opt)
|
||||
{
|
||||
char sbuf[16] = "";
|
||||
char *rubles = NULL;
|
||||
@@ -258,11 +257,10 @@ static switch_status_t ru_say_money(switch_core_session_t *session, char *tosay,
|
||||
int iruble = 0;
|
||||
int ikopecks = 0;
|
||||
int ikopeck = 0;
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " ru_say_money %s say_opt->currency=%d\n", tosay,say_opt->currency);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " ru_say_money %s\n", tosay);
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
@@ -279,58 +277,66 @@ static switch_status_t ru_say_money(switch_core_session_t *session, char *tosay,
|
||||
}
|
||||
|
||||
if (sbuf[0] == '-') {
|
||||
say_file("currency/minus.wav");
|
||||
switch_say_file(sh, "currency/minus");
|
||||
rubles++;
|
||||
}
|
||||
|
||||
ru_say_count(session, rubles, male_c, nominativus, args);
|
||||
|
||||
ru_say_count(sh, rubles, matrix_currency[say_opt->currency].first_gender,matrix_currency[say_opt->currency].first_cases);
|
||||
|
||||
if (rubles) {
|
||||
irubles = atoi(rubles) % 100;
|
||||
iruble = atoi(rubles) % 10;
|
||||
}
|
||||
|
||||
if (irubles == 1 || (irubles > 20 && iruble == 1)) { /* рубль */
|
||||
say_file("currency/ruble.wav");
|
||||
} else if ((irubles > 1 && irubles < 5) || (irubles > 20 && iruble > 1 && iruble < 5)) { /*рубля */
|
||||
say_file("currency/ruble-a.wav");
|
||||
} else { /*рублей */
|
||||
say_file("currency/rubles.wav");
|
||||
if (iruble<5) {
|
||||
if ((irubles>10)&&(irubles<15)) {
|
||||
switch_say_file(sh, "currency/%s",matrix_currency->first[5]);
|
||||
}
|
||||
else {
|
||||
switch_say_file(sh, "currency/%s",matrix_currency->first[iruble]);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
switch_say_file(sh, "currency/%s",matrix_currency->first[5]);
|
||||
}
|
||||
|
||||
|
||||
/* Say kopecks */
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " %s\n", kopecks);
|
||||
ru_say_count(session, kopecks, female_c, nominativus, args);
|
||||
ru_say_count(sh, kopecks, matrix_currency[say_opt->currency].second_gender,matrix_currency[say_opt->currency].second_cases);
|
||||
|
||||
if (kopecks) {
|
||||
ikopecks = atoi(kopecks) % 100;
|
||||
ikopeck = atoi(kopecks) % 10;
|
||||
}
|
||||
|
||||
if (ikopecks == 1 || (ikopecks > 20 && ikopeck == 1)) {
|
||||
/* копейка */
|
||||
say_file("currency/kopeck.wav");
|
||||
} else if ((ikopecks > 1 && ikopecks < 5) || (ikopecks > 20 && ikopeck > 1 && ikopeck < 5)) {
|
||||
/* копейки */
|
||||
say_file("currency/kopeck-i.wav");
|
||||
} else {
|
||||
/* копеек */
|
||||
say_file("currency/kopecks.wav");
|
||||
if (ikopeck<5) {
|
||||
if ((ikopecks>10)&&(ikopecks<15)) {
|
||||
switch_say_file(sh, "currency/%s",matrix_currency->second[5]);
|
||||
}
|
||||
else {
|
||||
switch_say_file(sh, "currency/%s",matrix_currency->second[ikopeck]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch_say_file(sh, "currency/%s",matrix_currency->second[5]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
static switch_status_t ru_say_time(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args,say_opt_t *say_opt)
|
||||
{
|
||||
int32_t t;
|
||||
char buf[80];
|
||||
switch_time_t target = 0, target_now = 0;
|
||||
switch_time_exp_t tm, tm_now;
|
||||
uint8_t say_date = 0, say_time = 0, say_year = 0, say_month = 0, say_dow = 0, say_day = 0, say_yesterday = 0, say_today = 0;
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
const char *tz = switch_channel_get_variable(channel, "timezone");
|
||||
const char *tz = NULL;
|
||||
tz = switch_say_file_handle_get_variable(sh, "timezone");
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " ru_say_time %s type=%d method=%d\n", tosay, say_args->type, say_args->method);
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " ru_say_time %s type=%d method=%d\n", tosay, say_args->type, say_args->method);
|
||||
|
||||
if (say_args->type == SST_TIME_MEASUREMENT) {
|
||||
int64_t hours = 0;
|
||||
@@ -339,7 +345,7 @@ static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay,
|
||||
int64_t r = 0;
|
||||
|
||||
if (strchr(tosay, ':')) {
|
||||
char *tme = switch_core_session_strdup(session, tosay);
|
||||
char *tme = strdup(tosay);
|
||||
char *p;
|
||||
|
||||
if ((p = strrchr(tme, ':'))) {
|
||||
@@ -355,6 +361,7 @@ static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay,
|
||||
minutes = atoi(tme);
|
||||
}
|
||||
}
|
||||
free(tme);
|
||||
} else {
|
||||
if ((seconds = atol(tosay)) <= 0) {
|
||||
seconds = (int64_t) switch_epoch_time_now(NULL);
|
||||
@@ -373,37 +380,37 @@ static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay,
|
||||
}
|
||||
|
||||
switch_snprintf(buf, sizeof(buf), "%u", (unsigned) hours);
|
||||
ru_say_count(session, buf, male_c, nominativus, args);
|
||||
ru_say_count(sh, buf, male, nominativus);
|
||||
|
||||
if (((hours % 10) == 1) && (hours != 11)) {
|
||||
/* час */
|
||||
say_file("time/hour.wav");
|
||||
switch_say_file(sh, "time/hour");
|
||||
} else if (((hours % 10 > 1) && (hours % 10 < 5)) && ((hours < 12) || (hours > 14))) {
|
||||
say_file("time/hours-a.wav"); /* часа */
|
||||
switch_say_file(sh, "time/hours-a"); /* часа */
|
||||
} else {
|
||||
say_file("time/hours.wav"); /* часов */
|
||||
switch_say_file(sh, "time/hours"); /* часов */
|
||||
}
|
||||
|
||||
switch_snprintf(buf, sizeof(buf), "%u", (unsigned) minutes); //перевести минуты в *char
|
||||
ru_say_count(session, buf, female_c, nominativus, args);
|
||||
ru_say_count(sh, buf, female, nominativus);
|
||||
|
||||
if (((minutes % 10) == 1) && (minutes != 11)) {
|
||||
say_file("time/minute.wav"); //минута
|
||||
switch_say_file(sh, "time/minute"); //минута
|
||||
} else if (((minutes % 10 > 1) && (minutes % 10 < 5)) && ((minutes < 12) || (minutes > 14))) {
|
||||
say_file("time/minutes-i.wav"); // минуты
|
||||
switch_say_file(sh, "time/minutes-i"); // минуты
|
||||
} else {
|
||||
say_file("time/minutes.wav"); //минут
|
||||
switch_say_file(sh, "time/minutes"); //минут
|
||||
}
|
||||
|
||||
if (seconds != 0) {
|
||||
switch_snprintf(buf, sizeof(buf), "%u", (unsigned) seconds);
|
||||
ru_say_count(session, buf, female_c, nominativus, args);
|
||||
ru_say_count(sh, buf, female, nominativus);
|
||||
if (((seconds % 10) == 1) && (seconds != 11)) {
|
||||
say_file("time/second.wav"); // секунда
|
||||
switch_say_file(sh, "time/second"); // секунда
|
||||
} else if (((seconds % 10 > 1) && (seconds % 10 < 5)) && ((seconds < 12) || (seconds > 14))) {
|
||||
say_file("time/seconds-i.wav"); // секуны
|
||||
switch_say_file(sh, "time/seconds-i"); // секуны
|
||||
} else {
|
||||
say_file("time/seconds.wav"); //секунд
|
||||
switch_say_file(sh, "time/seconds"); //секунд
|
||||
}
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -419,6 +426,7 @@ static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay,
|
||||
|
||||
if (tz) {
|
||||
int check = atoi(tz);
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz);
|
||||
if (check) {
|
||||
switch_time_exp_tz(&tm, target, check);
|
||||
switch_time_exp_tz(&tm_now, target_now, check);
|
||||
@@ -472,13 +480,13 @@ static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay,
|
||||
}
|
||||
|
||||
if (say_today) {
|
||||
say_file("time/today.wav");
|
||||
switch_say_file(sh, "time/today");
|
||||
}
|
||||
if (say_yesterday) {
|
||||
say_file("time/yesterday.wav");
|
||||
switch_say_file(sh, "time/yesterday");
|
||||
}
|
||||
if (say_dow) {
|
||||
say_file("time/day-%d.wav", tm.tm_wday);
|
||||
switch_say_file(sh, "time/day-%d", tm.tm_wday);
|
||||
}
|
||||
if (say_date) {
|
||||
say_year = say_month = say_day = say_dow = 1;
|
||||
@@ -486,74 +494,103 @@ static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay,
|
||||
}
|
||||
if (say_day) {
|
||||
switch_snprintf(buf, sizeof(buf), "%u", (unsigned) tm.tm_mday);
|
||||
ru_say_count(session, buf, male_h, genitivus, args);
|
||||
ru_say_count(sh, buf, male_h, genitivus);
|
||||
}
|
||||
if (say_month) {
|
||||
say_file("time/mon-%d.wav", tm.tm_mon);
|
||||
switch_say_file(sh, "time/mon-%d", tm.tm_mon);
|
||||
}
|
||||
if (say_year) {
|
||||
switch_snprintf(buf, sizeof(buf), "%u", (unsigned) (tm.tm_year + 1900));
|
||||
ru_say_count(session, buf, male_h, genitivus, args);
|
||||
say_file("time/h-year.wav");
|
||||
}
|
||||
if (say_month || say_year || say_date || say_dow) {
|
||||
say_file("time/at.wav");
|
||||
ru_say_count(sh, buf, male_h, genitivus);
|
||||
switch_say_file(sh, "time/h-year");
|
||||
}
|
||||
if (say_time) {
|
||||
if (say_month || say_year || say_date || say_dow) {
|
||||
switch_say_file(sh, "time/at");
|
||||
}
|
||||
switch_snprintf(buf, sizeof(buf), "%d:%d:%d", tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
say_args->type = SST_TIME_MEASUREMENT;
|
||||
ru_say_time(session, buf, say_args, args);
|
||||
ru_say_time(sh, buf, say_args,say_opt);
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t ru_ip(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
static switch_status_t ru_ip(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args,say_opt_t *say_opt)
|
||||
{
|
||||
char *a, *b, *c, *d;
|
||||
if (!(a = switch_core_session_strdup(session, tosay))) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
if (!(a = strdup(tosay))) {
|
||||
abort();
|
||||
// return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (!(b = strchr(a, '.'))) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
*b++ = '\0';
|
||||
|
||||
if (!(c = strchr(b, '.'))) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
*c++ = '\0';
|
||||
|
||||
if (!(d = strchr(c, '.'))) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
*d++ = '\0';
|
||||
|
||||
ru_say_count(session, a, male_c, nominativus, args);
|
||||
say_file("digits/dot.wav");
|
||||
ru_say_count(sh, a, male, nominativus);
|
||||
switch_say_file(sh, "digits/dot");
|
||||
|
||||
ru_say_count(session, b, male_c, nominativus, args);
|
||||
say_file("digits/dot.wav");
|
||||
ru_say_count(sh, b, male, nominativus);
|
||||
switch_say_file(sh, "digits/dot");
|
||||
|
||||
ru_say_count(session, c, male_c, nominativus, args);
|
||||
say_file("digits/dot.wav");
|
||||
ru_say_count(sh, c, male, nominativus);
|
||||
switch_say_file(sh, "digits/dot");
|
||||
|
||||
ru_say_count(session, d, male_c, nominativus, args);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
ru_say_count(sh, d, male, nominativus);
|
||||
end:
|
||||
free(a);
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t ru_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
{
|
||||
switch_say_callback_t say_cb = NULL;
|
||||
|
||||
static switch_status_t ru_say_spell(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args,say_opt_t *say_opt)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = tosay; p && *p; p++) {
|
||||
int a = tolower((int) *p);
|
||||
if (a >= '0' && a <= '9') {
|
||||
switch_say_file(sh, "digits/%c", a);
|
||||
} else {
|
||||
if (say_args->type == SST_NAME_SPELLED) {
|
||||
switch_say_file(sh, "ascii/%d", a);
|
||||
} else if (say_args->type == SST_NAME_PHONETIC) {
|
||||
switch_say_file(sh, "phonetic-ascii/%d", a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static switch_new_say_callback_ru_t choose_callback(switch_say_args_t *say_args)
|
||||
{
|
||||
|
||||
switch_new_say_callback_ru_t say_cb = NULL;
|
||||
switch (say_args->type) {
|
||||
case SST_NUMBER:
|
||||
case SST_ITEMS:
|
||||
case SST_PERSONS:
|
||||
case SST_MESSAGES:
|
||||
|
||||
say_cb = ru_say_general_count;
|
||||
break;
|
||||
case SST_TIME_MEASUREMENT:
|
||||
@@ -576,23 +613,176 @@ static switch_status_t ru_say(switch_core_session_t *session, char *tosay, switc
|
||||
break;
|
||||
case SST_NAME_SPELLED:
|
||||
case SST_NAME_PHONETIC:
|
||||
return switch_ivr_say_spell(session, tosay, say_args, args);
|
||||
say_cb = ru_say_spell;
|
||||
break;
|
||||
case SST_CURRENCY:
|
||||
say_cb = ru_say_money;
|
||||
break;
|
||||
default:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown Say type=[%d]\n", say_args->type);
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown Say type=[%d]\n", say_args->type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (say_cb) {
|
||||
return say_cb(session, tosay, say_args, args);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
return say_cb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static switch_status_t run_callback(switch_new_say_callback_ru_t say_cb, char *tosay, switch_say_args_t *say_args, switch_core_session_t *session, char **rstr)
|
||||
{
|
||||
switch_say_file_handle_t *sh;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_event_t *var_event = NULL;
|
||||
const char *cases=NULL;
|
||||
const char *gender=NULL;
|
||||
const char *currency=NULL;
|
||||
say_opt_t say_opt;
|
||||
say_opt.cases=0;
|
||||
say_opt.gender=0;
|
||||
say_opt.currency=0;
|
||||
if (session) {
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_channel_get_variables(channel, &var_event);
|
||||
// проверяем не заданы ли канальные переменные род, падеж, валюта
|
||||
gender = switch_channel_get_variable(channel, "gender");
|
||||
cases = switch_channel_get_variable(channel, "cases");
|
||||
currency = switch_channel_get_variable(channel, "currency");
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say!!! %s %s %s !\n",gender, cases,currency);
|
||||
if (cases) {
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say!!! %s!\n", cases);
|
||||
|
||||
if ((strcmp(cases,"nominativus")==0) || (strcmp(cases,"именительный")==0)) {
|
||||
say_opt.cases=(cases_t)0;
|
||||
}
|
||||
if ((strcmp(cases,"genitivus")==0) || (strcmp(cases,"родительный")==0)) {
|
||||
say_opt.cases=(cases_t)1;
|
||||
}
|
||||
if ((strcmp(cases,"dativus")==0) || (strcmp(cases,"дательный")==0)) {
|
||||
say_opt.cases=(cases_t)2;
|
||||
}
|
||||
if ((strcmp(cases,"accusativus_a")==0) || (strcmp(cases,"винительный_о")==0)) {
|
||||
say_opt.cases=(cases_t)3;
|
||||
}
|
||||
if ((strcmp(cases,"accusativus_i")==0) || (strcmp(cases,"винительный_н")==0)) {
|
||||
say_opt.cases=(cases_t)4;
|
||||
}
|
||||
if ((strcmp(cases,"instrumentalis")==0) || (strcmp(cases,"творительный")==0)) {
|
||||
say_opt.cases=(cases_t)5;
|
||||
}
|
||||
if ((strcmp(cases,"prepositive")==0) || (strcmp(cases,"предложный")==0)) {
|
||||
say_opt.cases=(cases_t)6;
|
||||
}
|
||||
}
|
||||
if (gender) {
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say!!! %s!\n", gender);
|
||||
|
||||
if ((strcmp(gender,"male")==0) || (strcmp(gender,"мужской")==0)) {
|
||||
say_opt.gender=(say_gender_t)0;
|
||||
}
|
||||
if ((strcmp(gender,"it")==0) || (strcmp(gender,"средний")==0)) {
|
||||
say_opt.gender=(say_gender_t)1;
|
||||
}
|
||||
if ((strcmp(gender,"female")==0) || (strcmp(gender,"женский")==0)) {
|
||||
say_opt.gender=(say_gender_t)2;
|
||||
}
|
||||
if ((strcmp(gender,"plural")==0) || (strcmp(gender,"множественное")==0)) {
|
||||
say_opt.gender=(say_gender_t)3;
|
||||
}
|
||||
if ((strcmp(gender,"male_h")==0) || (strcmp(gender,"мужской_порядковый")==0)) {
|
||||
say_opt.gender=(say_gender_t)4;
|
||||
}
|
||||
if ((strcmp(gender,"it_h")==0) || (strcmp(gender,"средний_порядковый")==0)) {
|
||||
say_opt.gender=(say_gender_t)5;
|
||||
}
|
||||
if ((strcmp(gender,"female_h")==0) || (strcmp(gender,"женский_порядковый")==0)) {
|
||||
say_opt.gender=(say_gender_t)6;
|
||||
}
|
||||
if ((strcmp(gender,"plural_h")==0) || (strcmp(gender,"множественное_порядковый")==0)) {
|
||||
say_opt.gender=(say_gender_t)7;
|
||||
}
|
||||
|
||||
}
|
||||
if (currency) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say!!! %s!\n", currency);
|
||||
|
||||
if ((strcmp(currency,"ruble")==0) || (strcmp(currency,"рубль")==0)) {
|
||||
say_opt.currency=(currency_t)0;
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "rul!!! \n");
|
||||
|
||||
}
|
||||
if ((strcmp(currency,"dollar")==0) || (strcmp(currency,"доллар")==0)) {
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "dollar!!! !\n");
|
||||
say_opt.currency=(currency_t)1;
|
||||
}
|
||||
}
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say!!! %s! say_opt.gender=%d say_opt.cases=%d\n", tosay,say_opt.gender,say_opt.cases);
|
||||
|
||||
}
|
||||
switch_say_file_handle_create(&sh, say_args->ext, &var_event);
|
||||
//запуск ru_ip,ru_say_money ...
|
||||
status = say_cb(sh, tosay, say_args,&say_opt);
|
||||
|
||||
if ((*rstr = switch_say_file_handle_detach_path(sh))) {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
switch_say_file_handle_destroy(&sh);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static switch_status_t ru_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
{
|
||||
|
||||
switch_new_say_callback_ru_t say_cb = NULL;
|
||||
char *string = NULL;
|
||||
switch_status_t status;
|
||||
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
|
||||
say_cb = choose_callback(say_args);
|
||||
|
||||
if (say_cb) {
|
||||
status = run_callback(say_cb, tosay, say_args, session, &string);
|
||||
if (session && string) {
|
||||
status = switch_ivr_play_file(session, NULL, string, args);
|
||||
}
|
||||
|
||||
switch_safe_free(string);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static switch_status_t ru_say_string(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, char **rstr)
|
||||
{
|
||||
|
||||
switch_new_say_callback_ru_t say_cb = NULL;
|
||||
char *string = NULL;
|
||||
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
say_cb = choose_callback(say_args);
|
||||
|
||||
if (say_cb) {
|
||||
status = run_callback(say_cb, tosay, say_args, session, &string);
|
||||
if (string) {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
*rstr = string;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_say_ru_load)
|
||||
{
|
||||
switch_say_interface_t *say_interface;
|
||||
@@ -601,6 +791,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_say_ru_load)
|
||||
say_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_SAY_INTERFACE);
|
||||
say_interface->interface_name = "ru";
|
||||
say_interface->say_function = ru_say;
|
||||
say_interface->say_string_function = ru_say_string;
|
||||
|
||||
/* indicate that the module should continue to be loaded */
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
//http://ru.wiktionary.org/wiki/%D0%BE%D0%B4%D0%B8%D0%BD
|
||||
//http://ru.wiktionary.org/wiki/%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%B9
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
million,
|
||||
thousand,
|
||||
@@ -22,29 +24,43 @@ typedef enum {
|
||||
//тип числа порядковое или количественное
|
||||
typedef enum {
|
||||
nominativus, // именительный Кто? Что?
|
||||
genitivus, // Родительный Кого? Чего?
|
||||
dativus, // дательный Кого? Что?
|
||||
genitivus, // Родительный Кого? Чего?
|
||||
dativus, // дательный Кого? Что?
|
||||
accusativus_a, // Винительный Кого? animate - одушевлённый
|
||||
accusativus_i, // Винительный Что? inanimate - неодушевлённый
|
||||
instrumentalis, // Творительный Кем? Чем?
|
||||
prepositive // Предложный О ком? О чём?
|
||||
} casus_t;
|
||||
prepositive // Предложный О ком? О чём?
|
||||
} cases_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
//количественный
|
||||
male_c, //мужского пола
|
||||
it_c, //среднего
|
||||
female_c, //женского
|
||||
plural_c, //множественное число
|
||||
male, //мужского пола
|
||||
it, //среднего
|
||||
female, //женского
|
||||
plural, //множественное число
|
||||
//порядковый
|
||||
male_h, //порядковое мужского пола
|
||||
it_h, //порядковое среднего
|
||||
female_h, //порядковое женского
|
||||
plural_h //порядковое множественное число
|
||||
} say_type_t;
|
||||
male_h, //порядковое мужского пола
|
||||
it_h, //порядковое среднего
|
||||
female_h, //порядковое женского
|
||||
plural_h //порядковое множественное число
|
||||
} say_gender_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
ruble,
|
||||
dollar,
|
||||
euro
|
||||
} currency_t;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
say_gender_t gender;
|
||||
cases_t cases;
|
||||
currency_t currency;
|
||||
} say_opt_t;
|
||||
|
||||
|
||||
struct say_t {
|
||||
char *num[8];
|
||||
@@ -52,7 +68,31 @@ struct say_t {
|
||||
char *million[14];
|
||||
int all;
|
||||
};
|
||||
struct say_cur_t {
|
||||
char *first[6];
|
||||
say_gender_t first_gender;
|
||||
cases_t first_cases;
|
||||
char *second[6];
|
||||
say_gender_t second_gender;
|
||||
cases_t second_cases;
|
||||
|
||||
};
|
||||
|
||||
// описываем как произносить валяюты от 0 до 5 дальше идёт номер рода и падежа (с нуля)
|
||||
//рубли
|
||||
#define c_0 {{"rubles","ruble","ruble-a","ruble-a","ruble-a","rubles"},male,nominativus,\
|
||||
{"kopecks","kopeck","kopeck-i","kopeck-i","kopeck-i","kopecks"},female,nominativus}
|
||||
|
||||
#define c_1 {{"dollars","dollar","dollara","dollara","dollara","dollars"},male,nominativus,\
|
||||
{"centov","cent","centa","centa","centa","centov"},male,nominativus}
|
||||
|
||||
#define c_2 {{"rubles","ruble","ruble-a","ruble-a","ruble-a","rubles"},male,nominativus,\
|
||||
{"kopecks","kopeck","kopeck-i","kopeck-i","kopeck-i","kopecks"},female,nominativus}
|
||||
|
||||
|
||||
|
||||
|
||||
typedef switch_status_t (*switch_new_say_callback_ru_t) (switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args,say_opt_t *say_opt);
|
||||
|
||||
//именительный
|
||||
//именительный количественный/числительное
|
||||
@@ -60,7 +100,7 @@ struct say_t {
|
||||
//мужской род родительный падеж
|
||||
|
||||
//первая строка описывае как произносить цифры от 0 до 5 потом пристаставка и окончания для остальных
|
||||
// тоже самое для тысяч и миллионов, только ещё с произношением тысяч и миллионов в вонце так же окончание для цифр
|
||||
// тоже самое для тысяч и миллионов, только ещё с произношением тысяч и миллионов в конце так же окончание для цифр
|
||||
// как произносить тысячи и миллионы берёт с цифры 5
|
||||
|
||||
#define m_00 {\
|
||||
@@ -96,23 +136,25 @@ struct say_t {
|
||||
//порядковый
|
||||
//мужской
|
||||
#define m_04 {\
|
||||
{"","","","","","","",""},\
|
||||
{"","","","","","","","","","","","","",""},\
|
||||
{"","","","","","","","","","","","","",""},\
|
||||
{"h-0m","h-1m","h-2m","h-3m","h-4m","h-5m","h-","m"},\
|
||||
{"","","1f","thousand","2f","thousands-i","3","thousands-i","4","thousands-i","5","thousands","",""},\
|
||||
{"","","","million","2","million-a","3","million-a","4","million-a","5","millions","",""},\
|
||||
0,\
|
||||
}\
|
||||
//средний
|
||||
|
||||
#define m_05 {\
|
||||
{"","","","","","","",""},\
|
||||
{"","","","","","","","","","","","","",""},\
|
||||
{"","","","","","","","","","","","","",""},\
|
||||
{"0","1n","2","3","4","5","",""},\
|
||||
{"","","1f","thousand","2f","thousands-i","3","thousands-i","4","thousands-i","5","thousands","",""},\
|
||||
{"","","","million","2","million-a","3","million-a","4","million-a","5","millions","",""},\
|
||||
0,\
|
||||
}\
|
||||
|
||||
//женский
|
||||
#define m_06 {\
|
||||
{"","","","","","","",""},\
|
||||
{"","","","","","","","","","","","","",""},\
|
||||
{"","","","","","","","","","","","","",""},\
|
||||
{"h-0f","h-1f","h-2f","h-3f","h-4f","h-5f","h-","f"},\
|
||||
{"","","1f","thousand","2f","thousands-i","3","thousands-i","4","thousands-i","5","thousands","",""},\
|
||||
{"","","1","million","2","million-a","3","million-a","4","million-a","5","millions","",""},\
|
||||
0,\
|
||||
}\
|
||||
|
||||
|
||||
@@ -90,11 +90,24 @@ SWITCH_MODULE_DEFINITION(mod_say_th, mod_say_th_load, NULL, NULL);
|
||||
static switch_status_t th_say_general_count(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
{
|
||||
int in;
|
||||
char sbuf[13] = "";
|
||||
char sbuf[128] = "";
|
||||
char digits[11];
|
||||
int i;
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -206,15 +219,6 @@ static switch_status_t th_say_general_count(switch_core_session_t *session, char
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSM_ITERATED:
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -422,7 +426,7 @@ static switch_status_t th_say_money(switch_core_session_t *session, char *tosay,
|
||||
char *dollars = NULL;
|
||||
char *cents = NULL;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
@@ -89,11 +89,24 @@ SWITCH_MODULE_DEFINITION(mod_say_zh, mod_say_zh_load, NULL, NULL);
|
||||
static switch_status_t zh_say_general_count(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
{
|
||||
int in;
|
||||
char sbuf[13] = "";
|
||||
char sbuf[128] = "";
|
||||
char digits[11];
|
||||
int i;
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -170,15 +183,6 @@ static switch_status_t zh_say_general_count(switch_core_session_t *session, char
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSM_ITERATED:
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = tosay; p && *p; p++) {
|
||||
say_file("digits/%c.wav", *p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -386,7 +390,7 @@ static switch_status_t zh_say_money(switch_core_session_t *session, char *tosay,
|
||||
char *dollars = NULL;
|
||||
char *cents = NULL;
|
||||
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
|
||||
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
+8
-2
@@ -200,7 +200,7 @@ void WINAPI ServiceCtrlHandler(DWORD control)
|
||||
/* the main service entry point */
|
||||
void WINAPI service_main(DWORD numArgs, char **args)
|
||||
{
|
||||
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT | SCF_CALIBRATE_CLOCK | SCF_USE_CLOCK_RT;
|
||||
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT | SCF_USE_NAT_MAPPING | SCF_CALIBRATE_CLOCK | SCF_USE_CLOCK_RT;
|
||||
const char *err = NULL; /* error value for return from freeswitch initialization */
|
||||
|
||||
/* Override flags if they have been set earlier */
|
||||
@@ -364,7 +364,7 @@ int main(int argc, char *argv[])
|
||||
#ifdef __sun
|
||||
switch_core_flag_t flags = SCF_USE_SQL;
|
||||
#else
|
||||
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT | SCF_CALIBRATE_CLOCK | SCF_USE_CLOCK_RT;
|
||||
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT | SCF_USE_NAT_MAPPING | SCF_CALIBRATE_CLOCK | SCF_USE_CLOCK_RT;
|
||||
#endif
|
||||
int ret = 0;
|
||||
switch_status_t destroy_status;
|
||||
@@ -412,6 +412,7 @@ int main(int argc, char *argv[])
|
||||
"\t-nosql -- disable internal sql scoreboard\n"
|
||||
"\t-heavy-timer -- Heavy Timer, possibly more accurate but at a cost\n"
|
||||
"\t-nonat -- disable auto nat detection\n"
|
||||
"\t-nonatmap -- disable auto nat port mapping\n"
|
||||
"\t-nocal -- disable clock calibration\n"
|
||||
"\t-nort -- disable clock clock_realtime\n"
|
||||
"\t-stop -- stop freeswitch\n"
|
||||
@@ -581,6 +582,11 @@ int main(int argc, char *argv[])
|
||||
known_opt++;
|
||||
}
|
||||
|
||||
if (local_argv[x] && !strcmp(local_argv[x], "-nonatmap")) {
|
||||
flags &= ~SCF_USE_NAT_MAPPING;
|
||||
known_opt++;
|
||||
}
|
||||
|
||||
if (local_argv[x] && !strcmp(local_argv[x], "-heavy-timer")) {
|
||||
flags |= SCF_USE_HEAVY_TIMING;
|
||||
known_opt++;
|
||||
|
||||
+59
-51
@@ -2456,8 +2456,8 @@ SWITCH_DECLARE(void) switch_channel_flip_cid(switch_channel_t *channel)
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_INFO, "%s Flipping CID from \"%s\" <%s> to \"%s\" <%s>\n",
|
||||
switch_channel_get_name(channel),
|
||||
switch_channel_get_variable(channel, "pre_transfer_caller_id_name"),
|
||||
switch_channel_get_variable(channel, "pre_transfer_caller_id_number"),
|
||||
switch_str_nil(switch_channel_get_variable(channel, "pre_transfer_caller_id_name")),
|
||||
switch_str_nil(switch_channel_get_variable(channel, "pre_transfer_caller_id_number")),
|
||||
channel->caller_profile->caller_id_name,
|
||||
channel->caller_profile->caller_id_number
|
||||
);
|
||||
@@ -2588,8 +2588,6 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(swi
|
||||
switch_ring_ready_t rv,
|
||||
const char *file, const char *func, int line)
|
||||
{
|
||||
const char *var;
|
||||
char *app;
|
||||
switch_event_t *event;
|
||||
|
||||
if (!switch_channel_test_flag(channel, CF_RING_READY) &&
|
||||
@@ -2619,21 +2617,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(swi
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE);
|
||||
if (var) {
|
||||
char *arg = NULL;
|
||||
app = switch_core_session_strdup(channel->session, var);
|
||||
|
||||
if (strstr(app, "::")) {
|
||||
switch_core_session_execute_application_async(channel->session, app, arg);
|
||||
} else {
|
||||
if ((arg = strchr(app, ' '))) {
|
||||
*arg++ = '\0';
|
||||
}
|
||||
|
||||
switch_core_session_execute_application(channel->session, app, arg);
|
||||
}
|
||||
}
|
||||
switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -2645,7 +2629,6 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_
|
||||
{
|
||||
switch_event_t *event;
|
||||
const char *var = NULL;
|
||||
char *app;
|
||||
|
||||
if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
|
||||
const char *uuid;
|
||||
@@ -2678,20 +2661,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_
|
||||
switch_mutex_unlock(channel->profile_mutex);
|
||||
}
|
||||
|
||||
if (((var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE)) ||
|
||||
(var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE))) && !zstr(var)) {
|
||||
char *arg = NULL;
|
||||
app = switch_core_session_strdup(channel->session, var);
|
||||
|
||||
|
||||
if (strstr(app, "::")) {
|
||||
switch_core_session_execute_application_async(channel->session, app, arg);
|
||||
} else {
|
||||
if ((arg = strchr(app, ' '))) {
|
||||
*arg++ = '\0';
|
||||
}
|
||||
|
||||
switch_core_session_execute_application(channel->session, app, arg);
|
||||
if (switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE) != SWITCH_STATUS_SUCCESS) {
|
||||
if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
|
||||
switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2785,6 +2757,42 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_ring_ready_value(switch_c
|
||||
return status;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix)
|
||||
{
|
||||
switch_event_header_t *hi;
|
||||
switch_event_t *event;
|
||||
int x = 0;
|
||||
|
||||
switch_channel_get_variables(channel, &event);
|
||||
|
||||
for (hi = event->headers; hi; hi = hi->next) {
|
||||
char *var = hi->name;
|
||||
char *val = hi->value;
|
||||
char *app;
|
||||
|
||||
if (!strncasecmp(var, variable_prefix, strlen(variable_prefix))) {
|
||||
char *arg = NULL;
|
||||
x++;
|
||||
|
||||
app = switch_core_session_strdup(channel->session, val);
|
||||
|
||||
if (strstr(app, "::")) {
|
||||
switch_core_session_execute_application_async(channel->session, app, arg);
|
||||
} else {
|
||||
if ((arg = strchr(app, ' '))) {
|
||||
*arg++ = '\0';
|
||||
}
|
||||
|
||||
switch_core_session_execute_application(channel->session, app, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch_event_destroy(&event);
|
||||
|
||||
return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_channel_t *channel, const char *file, const char *func, int line)
|
||||
{
|
||||
switch_event_t *event;
|
||||
@@ -2852,21 +2860,10 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_chan
|
||||
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Channel [%s] has been answered\n",
|
||||
channel->name);
|
||||
|
||||
if (((var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE)) ||
|
||||
(!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && (var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE))))
|
||||
&& !zstr(var)) {
|
||||
char *arg = NULL;
|
||||
|
||||
app = switch_core_session_strdup(channel->session, var);
|
||||
|
||||
if (strstr(app, "::")) {
|
||||
switch_core_session_execute_application_async(channel->session, app, arg);
|
||||
} else {
|
||||
if ((arg = strchr(app, ' '))) {
|
||||
*arg++ = '\0';
|
||||
}
|
||||
|
||||
switch_core_session_execute_application(channel->session, app, arg);
|
||||
if (switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE) != SWITCH_STATUS_SUCCESS) {
|
||||
if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
|
||||
switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2943,7 +2940,7 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
|
||||
char *data, *indup, *endof_indup;
|
||||
size_t sp = 0, len = 0, olen = 0, vtype = 0, br = 0, cpos, block = 128;
|
||||
char *cloned_sub_val = NULL, *sub_val = NULL;
|
||||
char *func_val = NULL;
|
||||
char *func_val = NULL, *sb = NULL;
|
||||
int nv = 0;
|
||||
|
||||
if (zstr(in)) {
|
||||
@@ -3033,8 +3030,19 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
|
||||
}
|
||||
p = e > endof_indup ? endof_indup : e;
|
||||
|
||||
if ((vval = strchr(vname, '(')) || (vval = strchr(vname, ' '))) {
|
||||
if (*vval == '(') br = 1;
|
||||
vval = NULL;
|
||||
for(sb = vname; sb && *sb; sb++) {
|
||||
if (*sb == ' ') {
|
||||
vval = sb;
|
||||
break;
|
||||
} else if (*sb == '(') {
|
||||
vval = sb;
|
||||
br = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (vval) {
|
||||
e = vval - 1;
|
||||
*vval++ = '\0';
|
||||
while (*e == ' ') {
|
||||
|
||||
+6
-6
@@ -1404,7 +1404,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
|
||||
}
|
||||
|
||||
if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) {
|
||||
switch_nat_init(runtime.memory_pool);
|
||||
switch_nat_init(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_NAT_MAPPING));
|
||||
}
|
||||
|
||||
switch_log_init(runtime.memory_pool, runtime.colorize_console);
|
||||
@@ -1661,18 +1661,18 @@ static void switch_load_core_config(const char *file)
|
||||
switch_core_default_dtmf_duration((uint32_t) tmp);
|
||||
}
|
||||
} else if (!strcasecmp(var, "enable-monotonic-timing")) {
|
||||
switch_time_set_monotonic(switch_true(var));
|
||||
switch_time_set_monotonic(switch_true(val));
|
||||
} else if (!strcasecmp(var, "enable-softtimer-timerfd")) {
|
||||
switch_time_set_timerfd(switch_true(var));
|
||||
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")) {
|
||||
switch_time_set_nanosleep(switch_true(var));
|
||||
switch_time_set_nanosleep(switch_true(val));
|
||||
} else if (!strcasecmp(var, "enable-cond-yield")) {
|
||||
switch_time_set_cond_yield(switch_true(var));
|
||||
switch_time_set_cond_yield(switch_true(val));
|
||||
} else if (!strcasecmp(var, "enable-timer-matrix")) {
|
||||
switch_time_set_matrix(switch_true(var));
|
||||
switch_time_set_matrix(switch_true(val));
|
||||
} else if (!strcasecmp(var, "max-sessions") && !zstr(val)) {
|
||||
switch_core_session_limit(atoi(val));
|
||||
} else if (!strcasecmp(var, "verbose-channel-events") && !zstr(val)) {
|
||||
|
||||
@@ -346,13 +346,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
||||
memset(session->raw_read_frame.data, 255, session->raw_read_frame.datalen);
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
} else {
|
||||
status = switch_core_codec_decode(use_codec,
|
||||
switch_thread_rwlock_rdlock(session->bug_rwlock);
|
||||
status = switch_core_codec_decode(use_codec->implementation?use_codec:read_frame->codec,
|
||||
session->read_codec,
|
||||
read_frame->data,
|
||||
read_frame->datalen,
|
||||
session->read_impl.actual_samples_per_second,
|
||||
session->raw_read_frame.data, &session->raw_read_frame.datalen, &session->raw_read_frame.rate,
|
||||
&read_frame->flags);
|
||||
switch_thread_rwlock_unlock(session->bug_rwlock);
|
||||
|
||||
}
|
||||
|
||||
if (status == SWITCH_STATUS_SUCCESS) {
|
||||
|
||||
@@ -606,6 +606,8 @@ SWITCH_DECLARE(char *) switch_cache_db_execute_sql2str(switch_cache_db_handle_t
|
||||
|
||||
if (io_mutex) switch_mutex_lock(io_mutex);
|
||||
|
||||
memset(str, 0, len);
|
||||
|
||||
switch (dbh->type) {
|
||||
case SCDB_TYPE_CORE_DB:
|
||||
{
|
||||
|
||||
@@ -306,7 +306,12 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
|
||||
|
||||
while ((state = switch_channel_get_state(session->channel)) != CS_DESTROY) {
|
||||
|
||||
switch_channel_wait_for_flag(session->channel, CF_BLOCK_STATE, SWITCH_FALSE, 0, NULL);
|
||||
if (switch_channel_test_flag(session->channel, CF_BLOCK_STATE)) {
|
||||
switch_channel_wait_for_flag(session->channel, CF_BLOCK_STATE, SWITCH_FALSE, 0, NULL);
|
||||
if ((state = switch_channel_get_state(session->channel)) == CS_DESTROY) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
midstate = state;
|
||||
if (state != switch_channel_get_running_state(session->channel) || state >= CS_HANGUP) {
|
||||
|
||||
+19
-3
@@ -1563,7 +1563,11 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
|
||||
char *cloned_sub_val = NULL;
|
||||
char *func_val = NULL;
|
||||
int nv = 0;
|
||||
char *gvar = NULL;
|
||||
char *gvar = NULL, *sb = NULL;
|
||||
|
||||
if (zstr(in)) {
|
||||
return (char *) in;
|
||||
}
|
||||
|
||||
nv = switch_string_var_check_const(in) || switch_string_has_escaped_data(in);
|
||||
|
||||
@@ -1647,10 +1651,22 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
|
||||
}
|
||||
p = e > endof_indup ? endof_indup : e;
|
||||
|
||||
if ((vval = strchr(vname, '(')) || (vval = strchr(vname, ' '))) {
|
||||
if (*vval == '(') br = 1;
|
||||
vval = NULL;
|
||||
for(sb = vname; sb && *sb; sb++) {
|
||||
if (*sb == ' ') {
|
||||
vval = sb;
|
||||
break;
|
||||
} else if (*sb == '(') {
|
||||
vval = sb;
|
||||
br = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (vval) {
|
||||
e = vval - 1;
|
||||
*vval++ = '\0';
|
||||
|
||||
while (*e == ' ') {
|
||||
*e-- = '\0';
|
||||
}
|
||||
|
||||
+155
-9
@@ -2330,22 +2330,38 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
|
||||
const char *save_path = NULL, *chan_lang = NULL, *lang = NULL, *lname = NULL, *sound_path = NULL;
|
||||
switch_event_t *hint_data;
|
||||
switch_xml_t cfg, xml = NULL, language, macros;
|
||||
|
||||
char *p;
|
||||
|
||||
switch_assert(session);
|
||||
channel = switch_core_session_get_channel(session);
|
||||
switch_assert(channel);
|
||||
|
||||
lang = switch_channel_get_variable(channel, "language");
|
||||
if (zstr(module_name)) {
|
||||
module_name = "en";
|
||||
}
|
||||
|
||||
if (!lang) {
|
||||
chan_lang = switch_channel_get_variable(channel, "default_language");
|
||||
if (!chan_lang) {
|
||||
chan_lang = "en";
|
||||
if (module_name) {
|
||||
p = switch_core_session_strdup(session, module_name);
|
||||
module_name = p;
|
||||
|
||||
if ((p = strchr(module_name, ':'))) {
|
||||
*p++ = '\0';
|
||||
chan_lang = p;
|
||||
}
|
||||
}
|
||||
|
||||
if (!chan_lang) {
|
||||
lang = switch_channel_get_variable(channel, "language");
|
||||
|
||||
if (!lang) {
|
||||
chan_lang = switch_channel_get_variable(channel, "default_language");
|
||||
if (!chan_lang) {
|
||||
chan_lang = module_name;
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang);
|
||||
} else {
|
||||
chan_lang = lang;
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang);
|
||||
} else {
|
||||
chan_lang = lang;
|
||||
}
|
||||
|
||||
switch_event_create(&hint_data, SWITCH_EVENT_REQUEST_PARAMS);
|
||||
@@ -2399,8 +2415,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
|
||||
|
||||
if (sound_path) {
|
||||
switch_channel_set_variable(channel, "sound_prefix", sound_path);
|
||||
p = switch_core_session_strdup(session, sound_path);
|
||||
sound_path = p;
|
||||
}
|
||||
|
||||
if (xml) {
|
||||
switch_xml_free(xml);
|
||||
}
|
||||
|
||||
if ((si = switch_loadable_module_get_say_interface(module_name))) {
|
||||
/* should go back and proto all the say mods to const.... */
|
||||
switch_say_args_t say_args = {0};
|
||||
@@ -2424,6 +2446,129 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
|
||||
if (save_path) {
|
||||
switch_channel_set_variable(channel, "sound_prefix", save_path);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_ivr_say_string(switch_core_session_t *session,
|
||||
const char *lang,
|
||||
const char *ext,
|
||||
const char *tosay,
|
||||
const char *module_name,
|
||||
const char *say_type,
|
||||
const char *say_method,
|
||||
const char *say_gender,
|
||||
char **rstr)
|
||||
{
|
||||
switch_say_interface_t *si;
|
||||
switch_channel_t *channel = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
const char *save_path = NULL, *chan_lang = NULL, *lname = NULL, *sound_path = NULL;
|
||||
switch_event_t *hint_data;
|
||||
switch_xml_t cfg, xml = NULL, language, macros;
|
||||
|
||||
if (session) {
|
||||
channel = switch_core_session_get_channel(session);
|
||||
|
||||
if (!lang) {
|
||||
lang = switch_channel_get_variable(channel, "language");
|
||||
|
||||
if (!lang) {
|
||||
chan_lang = switch_channel_get_variable(channel, "default_language");
|
||||
if (!chan_lang) {
|
||||
chan_lang = "en";
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang);
|
||||
} else {
|
||||
chan_lang = lang;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!lang) lang = "en";
|
||||
if (!chan_lang) chan_lang = lang;
|
||||
|
||||
switch_event_create(&hint_data, SWITCH_EVENT_REQUEST_PARAMS);
|
||||
switch_assert(hint_data);
|
||||
|
||||
switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "macro_name", "say_app");
|
||||
switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "lang", chan_lang);
|
||||
|
||||
if (channel) {
|
||||
switch_channel_event_set_data(channel, hint_data);
|
||||
}
|
||||
|
||||
if (switch_xml_locate("phrases", NULL, NULL, NULL, &xml, &cfg, hint_data, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Open of phrases failed.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!(macros = switch_xml_child(cfg, "macros"))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find macros tag.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!(language = switch_xml_child(macros, "language"))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find language tag.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
while (language) {
|
||||
if ((lname = (char *) switch_xml_attr(language, "name")) && !strcasecmp(lname, chan_lang)) {
|
||||
const char *tmp;
|
||||
|
||||
if ((tmp = switch_xml_attr(language, "module"))) {
|
||||
module_name = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
language = language->next;
|
||||
}
|
||||
|
||||
if (!language) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find language %s.\n", chan_lang);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!module_name) {
|
||||
module_name = chan_lang;
|
||||
}
|
||||
|
||||
if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) {
|
||||
sound_path = (char *) switch_xml_attr(language, "sound_path");
|
||||
}
|
||||
|
||||
if (channel) {
|
||||
save_path = switch_channel_get_variable(channel, "sound_prefix");
|
||||
}
|
||||
|
||||
if (sound_path && channel) {
|
||||
switch_channel_set_variable(channel, "sound_prefix", sound_path);
|
||||
}
|
||||
|
||||
if ((si = switch_loadable_module_get_say_interface(module_name))) {
|
||||
/* should go back and proto all the say mods to const.... */
|
||||
switch_say_args_t say_args = {0};
|
||||
|
||||
say_args.type = switch_ivr_get_say_type_by_name(say_type);
|
||||
say_args.method = switch_ivr_get_say_method_by_name(say_method);
|
||||
say_args.gender = switch_ivr_get_say_gender_by_name(say_gender);
|
||||
say_args.ext = ext;
|
||||
status = si->say_string_function(session, (char *) tosay, &say_args, rstr);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid SAY Interface [%s]!\n", module_name);
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if (hint_data) {
|
||||
switch_event_destroy(&hint_data);
|
||||
}
|
||||
|
||||
if (save_path && channel) {
|
||||
switch_channel_set_variable(channel, "sound_prefix", save_path);
|
||||
}
|
||||
|
||||
if (xml) {
|
||||
switch_xml_free(xml);
|
||||
@@ -2432,6 +2577,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static const char *get_prefixed_str(char *buffer, size_t buffer_size, const char *prefix, size_t prefix_size, const char *str)
|
||||
{
|
||||
size_t str_len;
|
||||
|
||||
@@ -357,11 +357,11 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
|
||||
}
|
||||
|
||||
|
||||
if ((bypass_media_after_bridge || switch_channel_test_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE)) && switch_channel_test_flag(chan_a, CF_ANSWERED)
|
||||
if ((bypass_media_after_bridge || switch_channel_test_flag(chan_b, CF_BYPASS_MEDIA_AFTER_BRIDGE)) && switch_channel_test_flag(chan_a, CF_ANSWERED)
|
||||
&& switch_channel_test_flag(chan_b, CF_ANSWERED)) {
|
||||
switch_ivr_nomedia(switch_core_session_get_uuid(session_a), SMF_REBRIDGE);
|
||||
bypass_media_after_bridge = 0;
|
||||
switch_channel_clear_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE);
|
||||
switch_channel_clear_flag(chan_b, CF_BYPASS_MEDIA_AFTER_BRIDGE);
|
||||
goto end_of_bridge_loop;
|
||||
}
|
||||
}
|
||||
@@ -1367,6 +1367,8 @@ static void cleanup_proxy_mode_a(switch_core_session_t *session)
|
||||
const char *sbv = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
|
||||
if (!zstr(sbv) && (sbsession = switch_core_session_locate(sbv))) {
|
||||
switch_channel_t *sbchannel = switch_core_session_get_channel(sbsession);
|
||||
/* Clear this now, otherwise will cause the one we're interested in to hang up too...*/
|
||||
switch_channel_set_variable(sbchannel, SWITCH_SIGNAL_BRIDGE_VARIABLE, NULL);
|
||||
switch_channel_hangup(sbchannel, SWITCH_CAUSE_ATTENDED_TRANSFER);
|
||||
switch_core_session_rwunlock(sbsession);
|
||||
}
|
||||
|
||||
@@ -2762,23 +2762,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
||||
switch_channel_set_variable(originate_status[i].peer_channel, "originating_leg_uuid", switch_core_session_get_uuid(session));
|
||||
}
|
||||
|
||||
if ((vvar = switch_channel_get_variable_dup(originate_status[i].peer_channel, "execute_on_originate", SWITCH_FALSE))) {
|
||||
char *app = switch_core_session_strdup(originate_status[i].peer_session, vvar);
|
||||
char *arg = NULL;
|
||||
|
||||
if (strstr(app, "::")) {
|
||||
switch_core_session_execute_application_async(originate_status[i].peer_session, app, arg);
|
||||
} else {
|
||||
if ((arg = strchr(app, ' '))) {
|
||||
*arg++ = '\0';
|
||||
}
|
||||
|
||||
switch_core_session_execute_application(originate_status[i].peer_session, app, arg);
|
||||
}
|
||||
|
||||
}
|
||||
switch_channel_execute_on(originate_status[i].peer_channel, "execute_on_originate");
|
||||
}
|
||||
|
||||
|
||||
if (table) {
|
||||
switch_channel_add_state_handler(originate_status[i].peer_channel, table);
|
||||
}
|
||||
|
||||
+73
-60
@@ -1000,7 +1000,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
switch_file_handle_t lfh;
|
||||
const char *p;
|
||||
char *title = "", *copyright = "", *software = "", *artist = "", *comment = "", *date = "";
|
||||
uint8_t asis = 0;
|
||||
char *ext;
|
||||
const char *prefix;
|
||||
const char *timer_name;
|
||||
@@ -1024,6 +1023,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
int more_data = 0;
|
||||
char *playback_vars, *tmp;
|
||||
switch_event_t *event;
|
||||
uint32_t test_native = 0, last_native = 0;
|
||||
|
||||
if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
@@ -1060,9 +1060,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
l16++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (play_delimiter) {
|
||||
file_dup = switch_core_session_strdup(session, file);
|
||||
argc = switch_separate_string(file_dup, play_delimiter, argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
@@ -1071,9 +1068,18 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
argv[0] = (char *) file;
|
||||
}
|
||||
|
||||
if (!fh) {
|
||||
fh = &lfh;
|
||||
memset(fh, 0, sizeof(lfh));
|
||||
}
|
||||
|
||||
if (fh->samples > 0) {
|
||||
sample_start = fh->samples;
|
||||
fh->samples = 0;
|
||||
}
|
||||
|
||||
for (cur = 0; switch_channel_ready(channel) && !done && cur < argc; cur++) {
|
||||
file = argv[cur];
|
||||
asis = 0;
|
||||
eof = 0;
|
||||
|
||||
if (cur) {
|
||||
@@ -1168,7 +1174,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
} else {
|
||||
ext = read_impl.iananame;
|
||||
file = switch_core_session_sprintf(session, "%s.%s", file, ext);
|
||||
asis = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1186,16 +1191,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
}
|
||||
}
|
||||
|
||||
if (!fh) {
|
||||
fh = &lfh;
|
||||
memset(fh, 0, sizeof(lfh));
|
||||
}
|
||||
|
||||
if (fh->samples > 0) {
|
||||
sample_start = fh->samples;
|
||||
fh->samples = 0;
|
||||
}
|
||||
|
||||
if ((prebuf = switch_channel_get_variable(channel, "stream_prebuffer"))) {
|
||||
int maybe = atoi(prebuf);
|
||||
if (maybe > 0) {
|
||||
@@ -1221,9 +1216,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
switch_channel_set_private(channel, "__fh", fh);
|
||||
switch_core_session_io_rwunlock(session);
|
||||
|
||||
if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
|
||||
asis = 1;
|
||||
}
|
||||
|
||||
if (!abuf) {
|
||||
switch_zmalloc(abuf, FILE_STARTSAMPLES * sizeof(*abuf));
|
||||
@@ -1275,43 +1267,46 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
switch_assert(fh->audio_buffer);
|
||||
}
|
||||
|
||||
if (asis) {
|
||||
codec_name = "L16";
|
||||
|
||||
if (!switch_core_codec_ready((&codec))) {
|
||||
if (switch_core_codec_init(&codec,
|
||||
codec_name,
|
||||
NULL,
|
||||
fh->samplerate,
|
||||
interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, pool) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
|
||||
SWITCH_LOG_DEBUG, "Codec Activated %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
|
||||
|
||||
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
|
||||
switch_core_session_io_write_lock(session);
|
||||
switch_channel_set_private(channel, "__fh", NULL);
|
||||
switch_core_session_io_rwunlock(session);
|
||||
|
||||
switch_core_file_close(fh);
|
||||
|
||||
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE);
|
||||
status = SWITCH_STATUS_GENERR;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
test_native = switch_test_flag(fh, SWITCH_FILE_NATIVE);
|
||||
|
||||
if (test_native) {
|
||||
write_frame.codec = switch_core_session_get_read_codec(session);
|
||||
samples = read_impl.samples_per_packet;
|
||||
framelen = read_impl.encoded_bytes_per_packet;
|
||||
} else {
|
||||
codec_name = "L16";
|
||||
|
||||
if (!switch_core_codec_ready((&codec))) {
|
||||
if (switch_core_codec_init(&codec,
|
||||
codec_name,
|
||||
NULL,
|
||||
fh->samplerate,
|
||||
interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, pool) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
|
||||
SWITCH_LOG_DEBUG, "Codec Activated %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
|
||||
|
||||
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
|
||||
switch_core_session_io_write_lock(session);
|
||||
switch_channel_set_private(channel, "__fh", NULL);
|
||||
switch_core_session_io_rwunlock(session);
|
||||
|
||||
switch_core_file_close(fh);
|
||||
|
||||
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE);
|
||||
status = SWITCH_STATUS_GENERR;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
write_frame.codec = &codec;
|
||||
|
||||
samples = codec.implementation->samples_per_packet;
|
||||
framelen = codec.implementation->decoded_bytes_per_packet;
|
||||
}
|
||||
|
||||
last_native = test_native;
|
||||
|
||||
if (timer_name && !timer.samplecount) {
|
||||
uint32_t len;
|
||||
@@ -1429,7 +1424,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
memset(abuf + bread, 255, framelen - bread);
|
||||
}
|
||||
|
||||
olen = asis ? framelen : ilen;
|
||||
olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
|
||||
do_speed = 0;
|
||||
} else if (fh->audio_buffer && (eof || (switch_buffer_inuse(fh->audio_buffer) > (switch_size_t) (framelen)))) {
|
||||
if (!(bread = switch_buffer_read(fh->audio_buffer, abuf, framelen))) {
|
||||
@@ -1440,30 +1435,48 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
}
|
||||
}
|
||||
|
||||
fh->offset_pos += asis ? bread : bread / 2;
|
||||
fh->offset_pos += switch_test_flag(fh, SWITCH_FILE_NATIVE) ? bread : bread / 2;
|
||||
|
||||
if (bread < framelen) {
|
||||
memset(abuf + bread, 255, framelen - bread);
|
||||
}
|
||||
|
||||
olen = asis ? framelen : ilen;
|
||||
olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
|
||||
} else {
|
||||
if (eof) {
|
||||
break;
|
||||
}
|
||||
olen = FILE_STARTSAMPLES;
|
||||
if (!asis) {
|
||||
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
|
||||
olen /= 2;
|
||||
}
|
||||
if (switch_core_file_read(fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
|
||||
eof++;
|
||||
continue;
|
||||
}
|
||||
switch_buffer_write(fh->audio_buffer, abuf, asis ? olen : olen * 2);
|
||||
|
||||
test_native = switch_test_flag(fh, SWITCH_FILE_NATIVE);
|
||||
|
||||
if (test_native != last_native) {
|
||||
if (test_native) {
|
||||
write_frame.codec = switch_core_session_get_read_codec(session);
|
||||
samples = read_impl.samples_per_packet;
|
||||
framelen = read_impl.encoded_bytes_per_packet;
|
||||
} else {
|
||||
write_frame.codec = &codec;
|
||||
samples = codec.implementation->samples_per_packet;
|
||||
framelen = codec.implementation->decoded_bytes_per_packet;
|
||||
}
|
||||
switch_buffer_zero(fh->audio_buffer);
|
||||
}
|
||||
|
||||
last_native = test_native;
|
||||
|
||||
switch_buffer_write(fh->audio_buffer, abuf, switch_test_flag(fh, SWITCH_FILE_NATIVE) ? olen : olen * 2);
|
||||
olen = switch_buffer_read(fh->audio_buffer, abuf, framelen);
|
||||
fh->offset_pos += olen / 2;
|
||||
|
||||
if (!asis) {
|
||||
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
|
||||
olen /= 2;
|
||||
}
|
||||
|
||||
@@ -1473,7 +1486,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
break;
|
||||
}
|
||||
|
||||
if (!asis) {
|
||||
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
|
||||
if (fh->speed > 2) {
|
||||
fh->speed = 2;
|
||||
} else if (fh->speed < -2) {
|
||||
@@ -1481,7 +1494,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
}
|
||||
}
|
||||
|
||||
if (!asis && fh->audio_buffer && last_speed > -1 && last_speed != fh->speed) {
|
||||
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->audio_buffer && last_speed > -1 && last_speed != fh->speed) {
|
||||
switch_buffer_zero(fh->sp_audio_buffer);
|
||||
}
|
||||
|
||||
@@ -1492,7 +1505,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
}
|
||||
|
||||
|
||||
if (!asis && fh->speed && do_speed) {
|
||||
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->speed && do_speed) {
|
||||
float factor = 0.25f * abs(fh->speed);
|
||||
switch_size_t newlen, supplement, step;
|
||||
short *bp = write_frame.data;
|
||||
@@ -1583,7 +1596,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
more_data = 0;
|
||||
write_frame.samples = (uint32_t) olen;
|
||||
|
||||
if (asis) {
|
||||
if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
|
||||
write_frame.datalen = (uint32_t) olen;
|
||||
} else {
|
||||
write_frame.datalen = write_frame.samples * 2;
|
||||
@@ -1596,12 +1609,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
||||
}
|
||||
#ifndef WIN32
|
||||
#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
|
||||
if (!asis && l16) {
|
||||
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && l16) {
|
||||
switch_swap_linear(write_frame.data, (int) write_frame.datalen / 2);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
if (!asis && fh->vol) {
|
||||
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->vol) {
|
||||
switch_change_sln_volume(write_frame.data, write_frame.datalen / 2, fh->vol);
|
||||
}
|
||||
|
||||
|
||||
@@ -1918,6 +1918,101 @@ SWITCH_DECLARE(void *) switch_loadable_module_create_interface(switch_loadable_m
|
||||
}
|
||||
}
|
||||
|
||||
struct switch_say_file_handle {
|
||||
char *ext;
|
||||
int cnt;
|
||||
struct switch_stream_handle stream;
|
||||
switch_event_t *param_event;
|
||||
};
|
||||
|
||||
SWITCH_DECLARE(char *) switch_say_file_handle_get_variable(switch_say_file_handle_t *sh, const char *var)
|
||||
{
|
||||
char *ret = NULL;
|
||||
|
||||
if (sh->param_event) {
|
||||
ret = switch_event_get_header(sh->param_event, var);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(char *) switch_say_file_handle_get_path(switch_say_file_handle_t *sh)
|
||||
{
|
||||
return (char *) sh->stream.data;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(char *) switch_say_file_handle_detach_path(switch_say_file_handle_t *sh)
|
||||
{
|
||||
char *path;
|
||||
|
||||
switch_assert(sh);
|
||||
path = (char *) sh->stream.data;
|
||||
sh->stream.data = NULL;
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(void) switch_say_file_handle_destroy(switch_say_file_handle_t **sh)
|
||||
{
|
||||
switch_assert(sh);
|
||||
|
||||
switch_safe_free((*sh)->stream.data);
|
||||
switch_safe_free((*sh)->ext);
|
||||
|
||||
if ((*sh)->param_event) {
|
||||
switch_event_destroy(&(*sh)->param_event);
|
||||
}
|
||||
free(*sh);
|
||||
*sh = NULL;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_say_file_handle_create(switch_say_file_handle_t **sh, const char *ext, switch_event_t **var_event)
|
||||
{
|
||||
switch_assert(sh);
|
||||
|
||||
if (zstr(ext)) {
|
||||
ext = "wav";
|
||||
}
|
||||
|
||||
*sh = malloc(sizeof(**sh));
|
||||
memset(*sh, 0, sizeof(**sh));
|
||||
|
||||
SWITCH_STANDARD_STREAM((*sh)->stream);
|
||||
|
||||
if (var_event) {
|
||||
(*sh)->param_event = *var_event;
|
||||
*var_event = NULL;
|
||||
}
|
||||
|
||||
(*sh)->ext = strdup(ext);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void) switch_say_file(switch_say_file_handle_t *sh, const char *fmt, ...)
|
||||
{
|
||||
char buf[256] = "";
|
||||
int ret;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
if ((ret = switch_vsnprintf(buf, sizeof(buf), fmt, ap)) > 0) {
|
||||
if (!sh->cnt++) {
|
||||
sh->stream.write_function(&sh->stream, "file_string://%s.%s", buf, sh->ext);
|
||||
} else {
|
||||
sh->stream.write_function(&sh->stream, "!%s.%s", buf, sh->ext);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
|
||||
+21
-2
@@ -51,6 +51,7 @@ typedef struct {
|
||||
char *descURL;
|
||||
char pub_addr[IP_LEN];
|
||||
char pvt_addr[IP_LEN];
|
||||
switch_bool_t mapping;
|
||||
} nat_globals_t;
|
||||
|
||||
static nat_globals_t nat_globals;
|
||||
@@ -207,9 +208,14 @@ static int init_pmp(void)
|
||||
return get_pmp_pubaddr(nat_globals.pub_addr);
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void) switch_nat_set_mapping(switch_bool_t mapping)
|
||||
{
|
||||
nat_globals.mapping = mapping;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void) switch_nat_reinit(void)
|
||||
{
|
||||
switch_nat_init(nat_globals_perm.pool);
|
||||
switch_nat_init(nat_globals_perm.pool, nat_globals.mapping);
|
||||
}
|
||||
|
||||
switch_status_t init_nat_monitor(switch_memory_pool_t *pool)
|
||||
@@ -392,7 +398,7 @@ SWITCH_DECLARE(void) switch_nat_thread_stop(void)
|
||||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool)
|
||||
SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool, switch_bool_t mapping)
|
||||
{
|
||||
/* try free dynamic data structures prior to resetting to 0 */
|
||||
FreeUPNPUrls(&nat_globals.urls);
|
||||
@@ -405,6 +411,8 @@ SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool)
|
||||
nat_globals_perm.pool = pool;
|
||||
}
|
||||
|
||||
nat_globals.mapping = mapping;
|
||||
|
||||
switch_find_local_ip(nat_globals.pvt_addr, sizeof(nat_globals.pvt_addr), NULL, AF_INET);
|
||||
|
||||
|
||||
@@ -577,6 +585,11 @@ SWITCH_DECLARE(switch_status_t) switch_nat_add_mapping_internal(switch_port_t po
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_event_t *event = NULL;
|
||||
|
||||
if (!nat_globals.mapping) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "NAT port mapping disabled\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
switch (nat_globals.nat_type) {
|
||||
case SWITCH_NAT_TYPE_PMP:
|
||||
status = switch_nat_add_mapping_pmp(port, proto, external_port);
|
||||
@@ -710,6 +723,12 @@ SWITCH_DECLARE(char *) switch_nat_status(void)
|
||||
(nat_globals.nat_type == SWITCH_NAT_TYPE_UPNP) ? "UPNP" : (nat_globals.nat_type == SWITCH_NAT_TYPE_PMP ? "NAT-PMP" : "UNKNOWN"),
|
||||
nat_globals.pub_addr);
|
||||
|
||||
if (nat_globals.mapping) {
|
||||
stream.write_function(&stream, "NAT port mapping enabled.\n");
|
||||
} else {
|
||||
stream.write_function(&stream, "NAT port mapping disabled.\n");
|
||||
}
|
||||
|
||||
switch_api_execute("show", "nat_map", NULL, &stream);
|
||||
|
||||
return stream.data; /* caller frees */
|
||||
|
||||
+6
-1
@@ -756,7 +756,8 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
|
||||
|
||||
while (globals.RUNNING == 1) {
|
||||
runtime.reference += STEP_MIC;
|
||||
while ((ts = time_now(runtime.offset)) < runtime.reference) {
|
||||
|
||||
while (((ts = time_now(runtime.offset)) + 100) < runtime.reference) {
|
||||
if (ts < last) {
|
||||
if (MONO) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Virtual Migration Detected! Syncing Clock\n");
|
||||
@@ -770,6 +771,10 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
|
||||
runtime.initiated += diff;
|
||||
rev_errs++;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT,
|
||||
"If you see this message many times try setting the param enable-clock-nanosleep to true in switch.conf.xml or consider a nicer machine to run me on. I AM *FREE* afterall.\n");
|
||||
|
||||
} else {
|
||||
rev_errs = 0;
|
||||
}
|
||||
|
||||
+8
-14
@@ -2579,13 +2579,13 @@ SWITCH_DECLARE(int) switch_isxdigit(int c)
|
||||
return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_N | _X)));
|
||||
}
|
||||
static const char *DOW[] = {
|
||||
"sat",
|
||||
"sun",
|
||||
"mon",
|
||||
"tue",
|
||||
"wed",
|
||||
"thu",
|
||||
"fri"
|
||||
"fri",
|
||||
"sat"
|
||||
};
|
||||
|
||||
SWITCH_DECLARE(const char *) switch_dow_int2str(int val) {
|
||||
@@ -2601,7 +2601,7 @@ SWITCH_DECLARE(int) switch_dow_str2int(const char *exp) {
|
||||
|
||||
for (x = 0; x < switch_arraylen(DOW); x++) {
|
||||
if (!strncasecmp(DOW[x], exp, 3)) {
|
||||
ret = x;
|
||||
ret = x + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2611,13 +2611,13 @@ SWITCH_DECLARE(int) switch_dow_str2int(const char *exp) {
|
||||
typedef enum {
|
||||
DOW_ERR = -2,
|
||||
DOW_EOF = -1,
|
||||
DOW_SAT = 0,
|
||||
DOW_SUN,
|
||||
DOW_SUN = 1,
|
||||
DOW_MON,
|
||||
DOW_TUE,
|
||||
DOW_WED,
|
||||
DOW_THU,
|
||||
DOW_FRI,
|
||||
DOW_SAT,
|
||||
DOW_HYPHEN = '-',
|
||||
DOW_COMA = ','
|
||||
} dow_t;
|
||||
@@ -2632,7 +2632,7 @@ static inline dow_t _dow_read_token(const char **s)
|
||||
} else if (**s == ',') {
|
||||
(*s)++;
|
||||
return DOW_COMA;
|
||||
} else if (**s >= '0' && **s <= '9') {
|
||||
} else if (**s >= '1' && **s <= '7') {
|
||||
dow_t r = **s - '0';
|
||||
(*s)++;
|
||||
return r;
|
||||
@@ -2664,14 +2664,8 @@ SWITCH_DECLARE(switch_bool_t) switch_dow_cmp(const char *exp, int val)
|
||||
} else {
|
||||
/* Valid day found */
|
||||
if (range_start != DOW_EOF) { /* Evaluating a range */
|
||||
if (range_start < cur) {
|
||||
if (val >= range_start && val <= cur) {
|
||||
return SWITCH_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (val >= cur && val <= range_start) {
|
||||
return SWITCH_TRUE;
|
||||
}
|
||||
if (val >= range_start && val <= cur) {
|
||||
return SWITCH_TRUE;
|
||||
}
|
||||
range_start = DOW_EOF;
|
||||
} else if (val == cur) {
|
||||
|
||||
+62
-66
@@ -56,6 +56,7 @@
|
||||
|
||||
#include <switch.h>
|
||||
#ifndef WIN32
|
||||
#include <sys/wait.h>
|
||||
#include <switch_private.h>
|
||||
#include <glob.h>
|
||||
#else /* we're on windoze :( */
|
||||
@@ -117,11 +118,6 @@ struct switch_xml_root { /* additional data for the root tag */
|
||||
char ***pi; /* processing instructions */
|
||||
short standalone; /* non-zero if <?xml standalone="yes"?> */
|
||||
char err[SWITCH_XML_ERRL]; /* error string */
|
||||
/*! is_main_xml_root */
|
||||
switch_bool_t is_main_xml_root;
|
||||
/*! rwlock */
|
||||
switch_thread_rwlock_t *rwlock;
|
||||
|
||||
};
|
||||
|
||||
char *SWITCH_XML_NIL[] = { NULL }; /* empty, null terminated array of strings */
|
||||
@@ -137,11 +133,13 @@ struct switch_xml_binding {
|
||||
static switch_xml_binding_t *BINDINGS = NULL;
|
||||
static switch_xml_t MAIN_XML_ROOT = NULL;
|
||||
static switch_memory_pool_t *XML_MEMORY_POOL = NULL;
|
||||
|
||||
static switch_thread_rwlock_t *B_RWLOCK = NULL;
|
||||
static switch_thread_rwlock_t *XML_RWLOCK = NULL;
|
||||
static switch_mutex_t *XML_LOCK = NULL;
|
||||
static switch_mutex_t *REFLOCK = NULL;
|
||||
static switch_mutex_t *FILE_LOCK = NULL;
|
||||
static switch_mutex_t *XML_GEN_LOCK = NULL;
|
||||
static switch_mutex_t *XML_FREE_LOCK = NULL;
|
||||
static switch_mutex_t *XML_RWFILE_LOCK = NULL;
|
||||
|
||||
|
||||
struct xml_section_t {
|
||||
const char *name;
|
||||
@@ -1245,6 +1243,7 @@ static int preprocess_exec(const char *cwd, const char *command, int write_fd, i
|
||||
}
|
||||
}
|
||||
close(fds[0]);
|
||||
waitpid(pid, NULL, 0);
|
||||
} else { /* child */
|
||||
close(fds[0]);
|
||||
dup2(fds[1], STDOUT_FILENO);
|
||||
@@ -1528,8 +1527,8 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_parse_file(const char *file)
|
||||
} else {
|
||||
abs = file;
|
||||
}
|
||||
/* Protection against running this code twice on the same filename */
|
||||
switch_mutex_lock(XML_RWFILE_LOCK);
|
||||
|
||||
switch_mutex_lock(FILE_LOCK);
|
||||
|
||||
if (!(new_file = switch_mprintf("%s%s%s.fsxml", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, abs))) {
|
||||
goto done;
|
||||
@@ -1553,14 +1552,19 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_parse_file(const char *file)
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
switch_mutex_unlock(FILE_LOCK);
|
||||
|
||||
if (write_fd > -1) {
|
||||
close(write_fd);
|
||||
}
|
||||
|
||||
if (fd > -1) {
|
||||
close(fd);
|
||||
}
|
||||
switch_mutex_unlock(XML_RWFILE_LOCK);
|
||||
|
||||
switch_safe_free(new_file);
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
@@ -1922,16 +1926,14 @@ SWITCH_DECLARE(switch_status_t) switch_xml_locate_user(const char *key,
|
||||
|
||||
SWITCH_DECLARE(switch_xml_t) switch_xml_root(void)
|
||||
{
|
||||
switch_xml_root_t root = NULL;
|
||||
switch_xml_t xml;
|
||||
|
||||
switch_thread_rwlock_rdlock(XML_RWLOCK);
|
||||
if (MAIN_XML_ROOT) {
|
||||
root = (switch_xml_root_t) MAIN_XML_ROOT;
|
||||
switch_thread_rwlock_rdlock(root->rwlock);
|
||||
}
|
||||
switch_thread_rwlock_unlock(XML_RWLOCK);
|
||||
|
||||
return (switch_xml_t) root;
|
||||
switch_mutex_lock(REFLOCK);
|
||||
xml = MAIN_XML_ROOT;
|
||||
xml->refs++;
|
||||
switch_mutex_unlock(REFLOCK);
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
struct destroy_xml {
|
||||
@@ -1975,14 +1977,15 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **e
|
||||
{
|
||||
char path_buf[1024];
|
||||
uint8_t errcnt = 0;
|
||||
switch_xml_t r = NULL, new_main;
|
||||
switch_xml_t new_main, r = NULL;
|
||||
|
||||
if (!reload) {
|
||||
r = switch_xml_root();
|
||||
}
|
||||
switch_mutex_lock(XML_LOCK);
|
||||
|
||||
if (r) {
|
||||
goto done;
|
||||
if (MAIN_XML_ROOT) {
|
||||
if (!reload) {
|
||||
r = switch_xml_root();
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR, "freeswitch.xml");
|
||||
@@ -1995,28 +1998,28 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **e
|
||||
new_main = NULL;
|
||||
errcnt++;
|
||||
} else {
|
||||
switch_xml_t old_root = NULL;
|
||||
switch_xml_root_t new_main_root = (switch_xml_root_t) new_main;
|
||||
|
||||
new_main_root->is_main_xml_root = SWITCH_TRUE;
|
||||
|
||||
switch_xml_t old_root;
|
||||
*err = "Success";
|
||||
|
||||
old_root = switch_xml_root();
|
||||
switch_mutex_lock(REFLOCK);
|
||||
|
||||
switch_set_flag(new_main, SWITCH_XML_ROOT);
|
||||
|
||||
switch_thread_rwlock_wrlock(XML_RWLOCK);
|
||||
old_root = MAIN_XML_ROOT;
|
||||
MAIN_XML_ROOT = new_main;
|
||||
switch_thread_rwlock_unlock(XML_RWLOCK);
|
||||
switch_set_flag(MAIN_XML_ROOT, SWITCH_XML_ROOT);
|
||||
MAIN_XML_ROOT->refs++;
|
||||
|
||||
if (old_root) {
|
||||
if (old_root->refs) {
|
||||
old_root->refs--;
|
||||
}
|
||||
|
||||
if (old_root) {
|
||||
switch_clear_flag(old_root, SWITCH_XML_ROOT);
|
||||
if (!old_root->refs) {
|
||||
switch_xml_free(old_root);
|
||||
}
|
||||
}
|
||||
|
||||
switch_xml_free(old_root);
|
||||
switch_mutex_unlock(REFLOCK);
|
||||
|
||||
/* switch_xml_free_in_thread(old_root); */
|
||||
}
|
||||
} else {
|
||||
*err = "Cannot Open log directory or XML Root!";
|
||||
@@ -2035,6 +2038,8 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **e
|
||||
|
||||
done:
|
||||
|
||||
switch_mutex_unlock(XML_LOCK);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -2056,11 +2061,12 @@ SWITCH_DECLARE(switch_status_t) switch_xml_init(switch_memory_pool_t *pool, cons
|
||||
XML_MEMORY_POOL = pool;
|
||||
*err = "Success";
|
||||
|
||||
switch_mutex_init(&XML_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
|
||||
switch_mutex_init(&REFLOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
|
||||
switch_mutex_init(&FILE_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
|
||||
switch_mutex_init(&XML_GEN_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
|
||||
switch_mutex_init(&XML_FREE_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
|
||||
switch_mutex_init(&XML_RWFILE_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
|
||||
|
||||
switch_thread_rwlock_create(&B_RWLOCK, XML_MEMORY_POOL);
|
||||
switch_thread_rwlock_create(&XML_RWLOCK, XML_MEMORY_POOL);
|
||||
|
||||
assert(pool != NULL);
|
||||
|
||||
@@ -2075,7 +2081,9 @@ SWITCH_DECLARE(switch_status_t) switch_xml_init(switch_memory_pool_t *pool, cons
|
||||
SWITCH_DECLARE(switch_status_t) switch_xml_destroy(void)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_thread_rwlock_wrlock(XML_RWLOCK);
|
||||
|
||||
switch_mutex_lock(XML_LOCK);
|
||||
switch_mutex_lock(REFLOCK);
|
||||
|
||||
if (MAIN_XML_ROOT) {
|
||||
switch_xml_t xml = MAIN_XML_ROOT;
|
||||
@@ -2084,7 +2092,8 @@ SWITCH_DECLARE(switch_status_t) switch_xml_destroy(void)
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
switch_thread_rwlock_unlock(XML_RWLOCK);
|
||||
switch_mutex_unlock(XML_LOCK);
|
||||
switch_mutex_unlock(REFLOCK);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -2370,35 +2379,25 @@ SWITCH_DECLARE(void) switch_xml_free(switch_xml_t xml)
|
||||
int i, j;
|
||||
char **a, *s;
|
||||
switch_xml_t orig_xml;
|
||||
int refs = 0;
|
||||
|
||||
tailrecurse:
|
||||
root = (switch_xml_root_t) xml;
|
||||
if (!xml) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If xml is currenly the MAIN_XML_ROOT, dont even bother to check to empty it */
|
||||
if (switch_test_flag(xml, SWITCH_XML_ROOT)) {
|
||||
switch_thread_rwlock_unlock(root->rwlock);
|
||||
return;
|
||||
}
|
||||
switch_mutex_lock(REFLOCK);
|
||||
|
||||
/* This is a trick to find if the struct is still in use or not */
|
||||
switch_mutex_lock(XML_FREE_LOCK);
|
||||
if (xml->is_switch_xml_root_t == SWITCH_TRUE && root->is_main_xml_root == SWITCH_TRUE) {
|
||||
switch_thread_rwlock_unlock(root->rwlock);
|
||||
if (switch_thread_rwlock_trywrlock(root->rwlock) != SWITCH_STATUS_SUCCESS) {
|
||||
/* XML Struct is still in used, person who free it will clean it */
|
||||
switch_mutex_unlock(XML_FREE_LOCK);
|
||||
return;
|
||||
if (xml->refs) {
|
||||
xml->refs--;
|
||||
refs = xml->refs;
|
||||
}
|
||||
switch_thread_rwlock_unlock(root->rwlock);
|
||||
switch_thread_rwlock_destroy(root->rwlock);
|
||||
switch_mutex_unlock(REFLOCK);
|
||||
}
|
||||
switch_mutex_unlock(XML_FREE_LOCK);
|
||||
|
||||
tailrecurse:
|
||||
root = (switch_xml_root_t) xml;
|
||||
if (!xml) {
|
||||
if (refs) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2447,7 +2446,6 @@ SWITCH_DECLARE(void) switch_xml_free(switch_xml_t xml)
|
||||
}
|
||||
|
||||
switch_xml_free_attr(xml->attr); /* tag attributes */
|
||||
|
||||
if ((xml->flags & SWITCH_XML_TXTM))
|
||||
free(xml->txt); /* character content */
|
||||
if ((xml->flags & SWITCH_XML_NAMEM))
|
||||
@@ -2485,8 +2483,6 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_new(const char *name)
|
||||
root->ent = (char **) memcpy(malloc(sizeof(ent)), ent, sizeof(ent));
|
||||
root->attr = root->pi = (char ***) (root->xml.attr = SWITCH_XML_NIL);
|
||||
root->xml.is_switch_xml_root_t = SWITCH_TRUE;
|
||||
root->is_main_xml_root = SWITCH_FALSE;
|
||||
switch_thread_rwlock_create(&root->rwlock, XML_MEMORY_POOL);
|
||||
return &root->xml;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user