diff --git a/Makefile.am b/Makefile.am
index df1ee2e0d0..8d35068c35 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -251,7 +251,8 @@ libfreeswitch_la_SOURCES = \
libs/miniupnpc/upnperrors.c \
libs/libnatpmp/natpmp.c \
libs/libnatpmp/getgateway.c\
- libs/spandsp/src/plc.c
+ libs/spandsp/src/plc.c \
+ libs/spandsp/src/bit_operations.c
if ENABLE_CPP
libfreeswitch_la_SOURCES += src/switch_cpp.cpp
diff --git a/build/modules.conf.in b/build/modules.conf.in
index 69d90a8dd4..2be000f6b3 100644
--- a/build/modules.conf.in
+++ b/build/modules.conf.in
@@ -35,6 +35,7 @@ applications/mod_valet_parking
#applications/mod_snapshot
#applications/mod_snipe_hunt
#applications/mod_callcenter
+#applications/mod_fsk
codecs/mod_g723_1
codecs/mod_amr
#codecs/mod_amrwb
diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml
index 51c62f2059..b7100bd304 100644
--- a/conf/autoload_configs/modules.conf.xml
+++ b/conf/autoload_configs/modules.conf.xml
@@ -56,6 +56,7 @@
+
diff --git a/libs/.gitignore b/libs/.gitignore
index cc42ba4fa4..b31646500e 100644
--- a/libs/.gitignore
+++ b/libs/.gitignore
@@ -1001,6 +1001,7 @@
/unimrcp/build/acmacros/lt~obsolete.m4
/*.tar.gz
/celt-0.7.1/
+/celt-0.10.0/
/flite-1.3.99/
/freeradius-client-1.1.6/
/iksemel/test/tst-dom
diff --git a/libs/freetdm/bootstrap b/libs/freetdm/bootstrap
index 8ca4856832..247d396da5 100755
--- a/libs/freetdm/bootstrap
+++ b/libs/freetdm/bootstrap
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
autoheader
libtoolize --force --copy
aclocal
diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c
index f50d26c290..778c5f403f 100755
--- a/libs/freetdm/mod_freetdm/mod_freetdm.c
+++ b/libs/freetdm/mod_freetdm/mod_freetdm.c
@@ -4177,6 +4177,19 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load)
freetdm_endpoint_interface->state_handler = &freetdm_state_handlers;
SWITCH_ADD_API(commands_api_interface, "ftdm", "FreeTDM commands", ft_function, FT_SYNTAX);
+ switch_console_set_complete("add ftdm start");
+ switch_console_set_complete("add ftdm stop");
+ switch_console_set_complete("add ftdm retart");
+ switch_console_set_complete("add ftdm dump");
+ switch_console_set_complete("add ftdm sigstatus get");
+ switch_console_set_complete("add ftdm sigstatus set");
+ switch_console_set_complete("add ftdm trace");
+ switch_console_set_complete("add ftdm notrace");
+ switch_console_set_complete("add ftdm q931_pcap");
+ switch_console_set_complete("add ftdm gains");
+ switch_console_set_complete("add ftdm dtmf on");
+ switch_console_set_complete("add ftdm dtmf off");
+
SWITCH_ADD_APP(app_interface, "disable_ec", "Disable Echo Canceller", "Disable Echo Canceller", disable_ec_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "disable_dtmf", "Disable DTMF Detection", "Disable DTMF Detection", disable_dtmf_function, "", SAF_NONE);
diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c
index cbaff7be54..211dcd0f6e 100644
--- a/libs/freetdm/src/ftdm_io.c
+++ b/libs/freetdm/src/ftdm_io.c
@@ -634,6 +634,10 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span)
ftdm_mutex_lock(span->mutex);
/* stop the signaling */
+
+ /* This is a forced stopped */
+ ftdm_clear_flag(span, FTDM_SPAN_NON_STOPPABLE);
+
ftdm_span_stop(span);
/* destroy the channels */
@@ -739,6 +743,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_stop(ftdm_span_t *span)
ftdm_status_t status = FTDM_SUCCESS;
ftdm_mutex_lock(span->mutex);
+
+ if (ftdm_test_flag(span, FTDM_SPAN_NON_STOPPABLE)) {
+ status = FTDM_NOTIMPL;
+ goto done;
+ }
if (!ftdm_test_flag(span, FTDM_SPAN_STARTED)) {
status = FTDM_EINVAL;
@@ -2288,7 +2297,8 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1);
break;
case FTDM_CHANNEL_INDICATE_PROCEED:
- if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE)) {
+ if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE) ||
+ ftdmchan->state == FTDM_CHANNEL_STATE_PROCEED) {
ftdm_ack_indication(ftdmchan, indication, status);
goto done;
}
@@ -2929,23 +2939,27 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
case FTDM_COMMAND_ENABLE_DTMF_DETECT:
{
/* if they don't have thier own, use ours */
- if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
- teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
- ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
- ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled software DTMF detector\n");
- GOTO_STATUS(done, FTDM_SUCCESS);
+ if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
+ if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
+ teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
+ ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
+ ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled software DTMF detector\n");
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
}
}
break;
case FTDM_COMMAND_DISABLE_DTMF_DETECT:
{
- if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
- teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
- ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
- ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled software DTMF detector\n");
- GOTO_STATUS(done, FTDM_SUCCESS);
+ if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
+ if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
+ teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
+ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
+ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled software DTMF detector\n");
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
}
}
break;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
index 01b2890bf1..f1e0bf45ce 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
@@ -1094,6 +1094,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE);
ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES);
+ ftdm_set_flag(span, FTDM_SPAN_NON_STOPPABLE);
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
span->trunk_type == FTDM_TRUNK_BRI) {
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
index 912d061963..2b43e9cea5 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
@@ -133,13 +133,12 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
get_redir_num(ftdmchan, &conEvnt->redirNmb);
get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad);
get_prog_ind_ie(ftdmchan, &conEvnt->progInd);
- get_facility_ie(ftdmchan, &conEvnt->facilityStr);
+ get_facility_ie(ftdmchan, &conEvnt->facilityStr);
if (get_calling_name_from_display(ftdmchan, &conEvnt->display) != FTDM_SUCCESS) {
get_calling_name_from_usr_usr(ftdmchan, &conEvnt->usrUsr);
}
-
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits);
if (conEvnt->bearCap[0].eh.pres) {
@@ -147,10 +146,17 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val);
}
-
if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
- snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
+ uint8_t encoding = (conEvnt->ni2OctStr.str.val[2] >> 5);
+ if (encoding == 0 || encoding == 1) {
+ /* BCD even or BCD odd */
+ uint8_t value = (conEvnt->ni2OctStr.str.val[3] & 0x0F)*10 + ((conEvnt->ni2OctStr.str.val[3] >> 4) & 0x0F);
+ snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", value);
+ } else if (encoding == 2) {
+ /* IA 5 */
+ snprintf(ftdmchan->caller_data.aniII, 5, "%c", conEvnt->ni2OctStr.str.val[3]);
+ }
}
}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
index 1591fb2a0e..9b4b7872c4 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
@@ -39,7 +39,7 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
ConEvnt conEvnt;
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
- ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_ORIG_NISDN};
+ ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
ftdm_assert((!sngisdn_info->suInstId && !sngisdn_info->spInstId), "Trying to call out, but call data was not cleared\n");
diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h
index d79835733b..3bc986d7f6 100644
--- a/libs/freetdm/src/include/private/ftdm_types.h
+++ b/libs/freetdm/src/include/private/ftdm_types.h
@@ -186,6 +186,9 @@ typedef enum {
/* If this flag is set, the signalling module supports jumping directly to state up, without
going through PROGRESS/PROGRESS_MEDIA */
FTDM_SPAN_USE_SKIP_STATES = (1 << 12),
+ /* If this flag is set, then this span cannot be stopped individually, it can only be stopped
+ on freetdm unload */
+ FTDM_SPAN_NON_STOPPABLE = (1 << 13),
} ftdm_span_flag_t;
/*! \brief Channel supported features */
diff --git a/libs/xmlrpc-c/lib/abyss/src/socket_win.c b/libs/xmlrpc-c/lib/abyss/src/socket_win.c
index 92b2b99cfb..d3f683a439 100644
--- a/libs/xmlrpc-c/lib/abyss/src/socket_win.c
+++ b/libs/xmlrpc-c/lib/abyss/src/socket_win.c
@@ -9,8 +9,7 @@
#include
#include
#include
-#include
-#include
+#include
#include "xmlrpc_config.h"
#include "xmlrpc-c/util_int.h"
@@ -249,6 +248,7 @@ struct socketWin {
SOCKET winsock;
bool userSuppliedWinsock;
/* 'socket' was supplied by the user; it belongs to him */
+ HANDLE interruptEvent;
};
static
@@ -322,6 +322,8 @@ channelDestroy(TChannel * const channelP) {
if (!socketWinP->userSuppliedWinsock)
closesocket(socketWinP->winsock);
+ CloseHandle(socketWinP->interruptEvent);
+
free(socketWinP);
}
@@ -430,9 +432,9 @@ channelWait(TChannel * const channelP,
timedOut = TRUE;
break;
case -1: /* socket error */
- if (errno != EINTR)
+ if (WSAGetLastError() != WSAEINTR)
failed = TRUE;
- break;
+ break;
default:
if (FD_ISSET(socketWinP->winsock, &rfds))
readRdy = TRUE;
@@ -460,7 +462,9 @@ channelInterrupt(TChannel * const channelP) {
now or in the future.
Actually, this is just a no-op because we don't yet know how to
- accomplish that.
+ accomplish that. (But we could probably do it the same way
+ chanSwitchInterrupt() works -- no one has needed it enough yet to do that
+ work).
-----------------------------------------------------------------------------*/
}
@@ -484,7 +488,7 @@ ChannelWinGetPeerName(TChannel * const channelP,
if (rc != 0) {
int const lastError = WSAGetLastError();
- xmlrpc_asprintf(errorP, "getpeername() failed. WSAERROR = %d (%s)",
+ xmlrpc_asprintf(errorP, "getpeername() failed. WSA error = %d (%s)",
lastError, getWSAError(lastError));
} else {
if (addrlen != sizeof(sockAddr))
@@ -581,7 +585,8 @@ makeChannelFromWinsock(SOCKET const winsock,
socketWinP->winsock = winsock;
socketWinP->userSuppliedWinsock = TRUE;
-
+ socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
ChannelCreate(&channelVtbl, socketWinP, &channelP);
if (channelP == NULL)
@@ -591,8 +596,10 @@ makeChannelFromWinsock(SOCKET const winsock,
*channelPP = channelP;
*errorP = NULL;
}
- if (*errorP)
+ if (*errorP) {
+ CloseHandle(socketWinP->interruptEvent);
free(socketWinP);
+ }
}
}
@@ -632,7 +639,7 @@ ChannelWinCreateWinsock(SOCKET const fd,
socklen_t peerAddrLen;
int rc;
- peerAddrLen = sizeof(peerAddrLen);
+ peerAddrLen = sizeof(peerAddr);
rc = getpeername(fd, &peerAddr, &peerAddrLen);
@@ -676,6 +683,8 @@ chanSwitchDestroy(TChanSwitch * const chanSwitchP) {
if (!socketWinP->userSuppliedWinsock)
closesocket(socketWinP->winsock);
+ CloseHandle(socketWinP->interruptEvent);
+
free(socketWinP);
}
@@ -711,6 +720,49 @@ chanSwitchListen(TChanSwitch * const chanSwitchP,
+static void
+createChannelForAccept(int const acceptedWinsock,
+ struct sockaddr const peerAddr,
+ TChannel ** const channelPP,
+ void ** const channelInfoPP,
+ const char ** const errorP) {
+
+ struct abyss_win_chaninfo * channelInfoP;
+ makeChannelInfo(&channelInfoP, peerAddr, sizeof(peerAddr), errorP);
+ if (!*errorP) {
+ struct socketWin * acceptedSocketP;
+
+ MALLOCVAR(acceptedSocketP);
+
+ if (!acceptedSocketP)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory");
+ else {
+ TChannel * channelP;
+
+ acceptedSocketP->winsock = acceptedWinsock;
+ acceptedSocketP->userSuppliedWinsock = FALSE;
+ acceptedSocketP->interruptEvent =
+ CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ ChannelCreate(&channelVtbl, acceptedSocketP, &channelP);
+ if (!channelP)
+ xmlrpc_asprintf(errorP,
+ "Failed to create TChannel object.");
+ else {
+ *errorP = NULL;
+ *channelPP = channelP;
+ *channelInfoPP = channelInfoP;
+ }
+ if (*errorP) {
+ CloseHandle(acceptedSocketP->interruptEvent);
+ free(acceptedSocketP);
+ }
+ }
+ }
+}
+
+
+
static SwitchAcceptImpl chanSwitchAccept;
static void
@@ -728,7 +780,7 @@ chanSwitchAccept(TChanSwitch * const chanSwitchP,
*channelPP == NULL.
-----------------------------------------------------------------------------*/
struct socketWin * const listenSocketP = chanSwitchP->implP;
-
+ HANDLE acceptEvent = WSACreateEvent();
bool interrupted;
TChannel * channelP;
@@ -736,46 +788,44 @@ chanSwitchAccept(TChanSwitch * const chanSwitchP,
channelP = NULL; /* No connection yet */
*errorP = NULL; /* No error yet */
+ WSAEventSelect(listenSocketP->winsock, acceptEvent,
+ FD_ACCEPT | FD_CLOSE | FD_READ);
+
while (!channelP && !*errorP && !interrupted) {
+ HANDLE interrupts[2] = {acceptEvent, listenSocketP->interruptEvent};
+ int rc;
struct sockaddr peerAddr;
socklen_t size = sizeof(peerAddr);
- int rc;
+
+ rc = WaitForMultipleObjects(2, interrupts, FALSE, INFINITE);
+ if (WAIT_OBJECT_0 + 1 == rc) {
+ interrupted = TRUE;
+ continue;
+ };
rc = accept(listenSocketP->winsock, &peerAddr, &size);
if (rc >= 0) {
int const acceptedWinsock = rc;
- struct socketWin * acceptedSocketP;
- MALLOCVAR(acceptedSocketP);
+ createChannelForAccept(acceptedWinsock, peerAddr,
+ &channelP, channelInfoPP, errorP);
- if (!acceptedSocketP)
- xmlrpc_asprintf(errorP, "Unable to allocate memory");
- else {
- acceptedSocketP->winsock = acceptedWinsock;
- acceptedSocketP->userSuppliedWinsock = FALSE;
-
- *channelInfoPP = NULL;
-
- ChannelCreate(&channelVtbl, acceptedSocketP, &channelP);
- if (!channelP)
- xmlrpc_asprintf(errorP,
- "Failed to create TChannel object.");
- else
- *errorP = NULL;
-
- if (*errorP)
- free(acceptedSocketP);
- }
if (*errorP)
closesocket(acceptedWinsock);
- } else if (errno == EINTR)
- interrupted = TRUE;
- else
- xmlrpc_asprintf(errorP, "accept() failed, errno = %d (%s)",
- errno, strerror(errno));
+ } else {
+ int const lastError = WSAGetLastError();
+
+ if (lastError == WSAEINTR)
+ interrupted = TRUE;
+ else
+ xmlrpc_asprintf(errorP,
+ "accept() failed, WSA error = %d (%s)",
+ lastError, getWSAError(lastError));
+ }
}
*channelPP = channelP;
+ CloseHandle(acceptEvent);
}
@@ -787,15 +837,10 @@ chanSwitchInterrupt(TChanSwitch * const chanSwitchP) {
/*----------------------------------------------------------------------------
Interrupt any waiting that a thread might be doing in chanSwitchAccept()
now or in the future.
-
- Actually, this is just a no-op because we don't yet know how to
- accomplish that.
-----------------------------------------------------------------------------*/
- struct socketWin * const socketWinP = chanSwitchP->implP;
-
- if (!socketWinP->userSuppliedWinsock)
- closesocket(socketWinP->winsock);
+ struct socketWin * const listenSocketP = chanSwitchP->implP;
+ SetEvent(listenSocketP->interruptEvent);
}
@@ -889,6 +934,7 @@ ChanSwitchWinCreate(uint16_t const portNumber,
} else {
socketWinP->winsock = winsock;
socketWinP->userSuppliedWinsock = FALSE;
+ socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
setSocketOptions(socketWinP->winsock, errorP);
if (!*errorP) {
@@ -899,8 +945,10 @@ ChanSwitchWinCreate(uint16_t const portNumber,
chanSwitchPP);
}
- if (*errorP)
+ if (*errorP) {
+ CloseHandle(socketWinP->interruptEvent);
closesocket(winsock);
+ }
}
if (*errorP)
free(socketWinP);
@@ -929,7 +977,8 @@ ChanSwitchWinCreateWinsock(SOCKET const winsock,
socketWinP->winsock = winsock;
socketWinP->userSuppliedWinsock = TRUE;
-
+ socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
ChanSwitchCreate(&chanSwitchVtbl, socketWinP, &chanSwitchP);
if (chanSwitchP == NULL)
@@ -939,8 +988,10 @@ ChanSwitchWinCreateWinsock(SOCKET const winsock,
*chanSwitchPP = chanSwitchP;
*errorP = NULL;
}
- if (*errorP)
+ if (*errorP) {
+ CloseHandle(socketWinP->interruptEvent);
free(socketWinP);
+ }
}
}
}
diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index ff131acb17..29e8b43526 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -116,7 +116,6 @@ struct switch_core_session;
struct switch_core_runtime;
struct switch_core_port_allocator;
-
/*!
\defgroup core1 Core Library
\ingroup FREESWITCH
@@ -713,6 +712,7 @@ SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *sessio
SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine);
SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session);
+SWITCH_DECLARE(switch_status_t) switch_core_session_set_codec_slin(switch_core_session_t *session, switch_slin_data_t *data);
/*!
\brief Retrieve the unique identifier from the core
diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h
index 1cf01c54bc..114e594c0c 100644
--- a/src/include/switch_module_interfaces.h
+++ b/src/include/switch_module_interfaces.h
@@ -711,6 +711,14 @@ struct switch_api_interface {
#define PROTECT_INTERFACE(_it) if (_it) {switch_mutex_lock(_it->reflock); switch_thread_rwlock_rdlock(_it->parent->rwlock); switch_thread_rwlock_rdlock(_it->rwlock); _it->refs++; _it->parent->refs++; switch_mutex_unlock(_it->reflock);} //if (!strcmp(_it->interface_name, "user")) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "+++++++++++LOCK %s %d/%d\n", _it->interface_name, _it->refs, _it->parent->refs);
#define UNPROTECT_INTERFACE(_it) if (_it) {switch_mutex_lock(_it->reflock); switch_thread_rwlock_unlock(_it->rwlock); switch_thread_rwlock_unlock(_it->parent->rwlock); _it->refs--; _it->parent->refs--; switch_mutex_unlock(_it->reflock);} //if (!strcmp(_it->interface_name, "user")) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "---------UNLOCK %s %d/%d\n", _it->interface_name, _it->refs, _it->parent->refs);
+#include "switch_frame.h"
+
+struct switch_slin_data {
+ switch_core_session_t *session;
+ switch_frame_t write_frame;
+ switch_codec_t codec;
+ char frame_data[SWITCH_RECOMMENDED_BUFFER_SIZE];
+};
SWITCH_END_EXTERN_C
#endif
diff --git a/src/include/switch_odbc.h b/src/include/switch_odbc.h
index f76384003a..103fe0f0d7 100644
--- a/src/include/switch_odbc.h
+++ b/src/include/switch_odbc.h
@@ -34,6 +34,8 @@
#include
+#define DEFAULT_ODBC_RETRIES 120
+
SWITCH_BEGIN_EXTERN_C struct switch_odbc_handle;
typedef void *switch_odbc_statement_handle_t;
@@ -50,6 +52,7 @@ typedef enum {
} switch_odbc_status_t;
SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, const char *username, const char *password);
+SWITCH_DECLARE(void) switch_odbc_set_num_retries(switch_odbc_handle_t *handle, int num_retries);
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_handle_t *handle);
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_handle_t *handle);
SWITCH_DECLARE(void) switch_odbc_handle_destroy(switch_odbc_handle_t **handlep);
diff --git a/src/include/switch_types.h b/src/include/switch_types.h
index 01f890d51c..9a5e09db7c 100644
--- a/src/include/switch_types.h
+++ b/src/include/switch_types.h
@@ -632,9 +632,13 @@ typedef enum {
This flag will never send any. Sheesh....
*/
+ RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6)
-
-
+ /*
+ Guess Who? ... Yep, Sonus (and who know's who else) likes to interweave DTMF with the audio stream making it take
+ 2X as long as it should and sending an incorrect duration making the DTMF very delayed.
+ This flag will treat every dtmf as if it were 50ms and queue it on recipt of the leading packet rather than at the end.
+ */
} switch_rtp_bug_flag_t;
@@ -1817,6 +1821,8 @@ typedef struct switch_loadable_module_function_table {
typedef int (*switch_modulename_callback_func_t) (void *user_data, const char *module_name);
+typedef struct switch_slin_data switch_slin_data_t;
+
#define SWITCH_MODULE_DEFINITION_EX(name, load, shutdown, runtime, flags) \
static const char modname[] = #name ; \
SWITCH_MOD_DECLARE_DATA switch_loadable_module_function_table_t name##_module_interface = { \
diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index 4602dd2bc5..41417255bb 100755
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -1485,6 +1485,8 @@ SWITCH_STANDARD_APP(ivr_application_function)
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to find menu\n");
}
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No menus configured\n");
}
switch_xml_free(cxml);
} else {
diff --git a/src/mod/applications/mod_fsk/Makefile b/src/mod/applications/mod_fsk/Makefile
new file mode 100644
index 0000000000..620f3f751c
--- /dev/null
+++ b/src/mod/applications/mod_fsk/Makefile
@@ -0,0 +1,6 @@
+BASE=../../../..
+
+LOCAL_SOURCES=fsk.c uart.c fsk_callerid.c
+LOCAL_OBJS=fsk.o uart.o fsk_callerid.o
+include $(BASE)/build/modmake.rules
+
diff --git a/src/mod/applications/mod_fsk/fsk.c b/src/mod/applications/mod_fsk/fsk.c
new file mode 100644
index 0000000000..773b0deaae
--- /dev/null
+++ b/src/mod/applications/mod_fsk/fsk.c
@@ -0,0 +1,351 @@
+
+/*
+ * bell202.c
+ *
+ * Copyright (c) 2005 Robert Krten. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * This module contains a Bell-202 1200-baud FSK decoder, suitable for
+ * use in a library. The general style of the library calls is modeled
+ * after the POSIX pthread_*() functions.
+ *
+ * 2005 03 20 R. Krten created
+*/
+
+#include
+#include
+#include
+#include
+#include
+
+#include "fsk.h"
+#include "uart.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+fsk_modem_definition_t fsk_modem_definitions[] =
+{
+ { /* FSK_V23_FORWARD_MODE1 */ 1700, 1300, 600 },
+ { /* FSK_V23_FORWARD_MODE2 */ 2100, 1300, 1200 },
+ { /* FSK_V23_BACKWARD */ 450, 390, 75 },
+ { /* FSK_BELL202 */ 2200, 1200, 1200 },
+};
+
+/*
+ * dsp_fsk_attr_init
+ *
+ * Initializes the attributes structure; this must be done before the
+ * attributes structure is used.
+*/
+
+void dsp_fsk_attr_init (dsp_fsk_attr_t *attr)
+{
+ memset(attr, 0, sizeof(*attr));
+}
+
+/*
+ * dsp_fsk_attr_get_bithandler
+ * dsp_fsk_attr_set_bithandler
+ * dsp_fsk_attr_get_bytehandler
+ * dsp_fsk_attr_set_bytehandler
+ * dsp_fsk_attr_getsamplerate
+ * dsp_fsk_attr_setsamplerate
+ *
+ * These functions get and set their respective elements from the
+ * attributes structure. If an error code is returned, it is just
+ * zero == ok, -1 == fail.
+*/
+
+bithandler_func_t dsp_fsk_attr_get_bithandler(dsp_fsk_attr_t *attr, void **bithandler_arg)
+{
+ *bithandler_arg = attr->bithandler_arg;
+ return attr->bithandler;
+}
+
+void dsp_fsk_attr_set_bithandler(dsp_fsk_attr_t *attr, bithandler_func_t bithandler, void *bithandler_arg)
+{
+ attr->bithandler = bithandler;
+ attr->bithandler_arg = bithandler_arg;
+}
+
+bytehandler_func_t dsp_fsk_attr_get_bytehandler(dsp_fsk_attr_t *attr, void **bytehandler_arg)
+{
+ *bytehandler_arg = attr->bytehandler_arg;
+ return attr->bytehandler;
+}
+
+void dsp_fsk_attr_set_bytehandler(dsp_fsk_attr_t *attr, bytehandler_func_t bytehandler, void *bytehandler_arg)
+{
+ attr->bytehandler = bytehandler;
+ attr->bytehandler_arg = bytehandler_arg;
+}
+
+int dsp_fsk_attr_get_samplerate (dsp_fsk_attr_t *attr)
+{
+ return attr->sample_rate;
+}
+
+int dsp_fsk_attr_set_samplerate (dsp_fsk_attr_t *attr, int samplerate)
+{
+ if (samplerate <= 0) {
+ return -1;
+ }
+ attr->sample_rate = samplerate;
+ return 0;
+}
+
+/*
+ * dsp_fsk_create
+ *
+ * Creates a handle for subsequent use. The handle is created to contain
+ * a context data structure for use by the sample handler function. The
+ * function expects an initialized attributes structure, and returns the
+ * handle or a NULL if there were errors.
+ *
+ * Once created, the handle can be used until it is destroyed.
+*/
+
+dsp_fsk_handle_t *dsp_fsk_create(dsp_fsk_attr_t *attr)
+{
+ int i;
+ double phi_mark, phi_space;
+ dsp_fsk_handle_t *handle;
+
+ handle = malloc(sizeof(*handle));
+ if (!handle) {
+ return NULL;
+ }
+
+ memset(handle, 0, sizeof(*handle));
+
+ /* fill the attributes member */
+ memcpy(&handle->attr, attr, sizeof(*attr));
+
+ /* see if we can do downsampling. We only really need 6 samples to "match" */
+ if (attr->sample_rate / fsk_modem_definitions[FSK_BELL202].freq_mark > 6) {
+ handle->downsampling_count = attr->sample_rate / fsk_modem_definitions[FSK_BELL202].freq_mark / 6;
+ } else {
+ handle->downsampling_count = 1;
+ }
+ handle->current_downsample = 1;
+
+ /* calculate the correlate size (number of samples required for slowest wave) */
+ handle->corrsize = attr->sample_rate / handle->downsampling_count / fsk_modem_definitions[FSK_BELL202].freq_mark;
+
+ /* allocate the correlation sin/cos arrays and initialize */
+ for (i = 0; i < 4; i++) {
+ handle->correlates[i] = malloc(sizeof(double) * handle->corrsize);
+ if (handle->correlates[i] == NULL) {
+ /* some failed, back out memory allocations */
+ dsp_fsk_destroy(&handle);
+ return NULL;
+ }
+ }
+
+ /* now initialize them */
+ phi_mark = 2. * M_PI / ((double) attr->sample_rate / (double) handle->downsampling_count / (double) fsk_modem_definitions[FSK_BELL202].freq_mark);
+ phi_space = 2. * M_PI / ((double) attr->sample_rate / (double) handle->downsampling_count / (double) fsk_modem_definitions[FSK_BELL202].freq_space);
+
+ for (i = 0; i < handle->corrsize; i++) {
+ handle->correlates[0][i] = sin(phi_mark * (double) i);
+ handle->correlates[1][i] = cos(phi_mark * (double) i);
+ handle->correlates[2][i] = sin(phi_space * (double) i);
+ handle->correlates[3][i] = cos(phi_space * (double) i);
+ }
+
+ /* initialize the ring buffer */
+ handle->buffer = malloc(sizeof(double) * handle->corrsize);
+ if (!handle->buffer) { /* failed; back out memory allocations */
+ dsp_fsk_destroy(&handle);
+ return NULL;
+ }
+ memset(handle->buffer, 0, sizeof(double) * handle->corrsize);
+ handle->ringstart = 0;
+
+ /* initalize intra-cell position */
+ handle->cellpos = 0;
+ handle->celladj = fsk_modem_definitions[FSK_BELL202].baud_rate / (double) attr->sample_rate * (double) handle->downsampling_count;
+
+ /* if they have provided a byte handler, add a UART to the processing chain */
+ if (handle->attr.bytehandler) {
+ dsp_uart_attr_t uart_attr;
+ dsp_uart_handle_t *uart_handle;
+
+ dsp_uart_attr_init(&uart_attr);
+ dsp_uart_attr_set_bytehandler(&uart_attr, handle->attr.bytehandler, handle->attr.bytehandler_arg);
+ uart_handle = dsp_uart_create(&uart_attr);
+ if (uart_handle == NULL) {
+ dsp_fsk_destroy(&handle);
+ return NULL;
+ }
+ handle->attr.bithandler = dsp_uart_bit_handler;
+ handle->attr.bithandler_arg = uart_handle;
+ }
+
+ return handle;
+}
+
+/*
+ * dsp_fsk_destroy
+ *
+ * Destroys a handle, releasing any associated memory. Sets handle pointer to NULL
+ * so A destroyed handle can not be used for anything after the destroy.
+*/
+
+void dsp_fsk_destroy(dsp_fsk_handle_t **handle)
+{
+ int i;
+
+ /* if empty handle, just return */
+ if (*handle == NULL) {
+ return;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if ((*handle)->correlates[i] != NULL) {
+ free((*handle)->correlates[i]);
+ (*handle)->correlates[i] = NULL;
+ }
+ }
+
+ if ((*handle)->buffer != NULL) {
+ free((*handle)->buffer);
+ (*handle)->buffer = NULL;
+ }
+
+ if ((*handle)->attr.bytehandler) {
+ dsp_uart_handle_t** dhandle = (void *)(&(*handle)->attr.bithandler_arg);
+ dsp_uart_destroy(dhandle);
+ }
+
+ free(*handle);
+ *handle = NULL;
+}
+
+/*
+ * dsp_fsk_sample
+ *
+ * This is the main processing entry point. The function accepts a normalized
+ * sample (i.e., one whose range is between -1 and +1). The function performs
+ * the Bell-202 FSK modem decode processing, and, if it detects a valid bit,
+ * will call the bithandler associated with the attributes structure.
+ *
+ * For the Bell-202 standard, a logical zero (space) is 2200 Hz, and a logical
+ * one (mark) is 1200 Hz.
+*/
+
+void
+dsp_fsk_sample (dsp_fsk_handle_t *handle, double normalized_sample)
+{
+ double val;
+ double factors[4];
+ int i, j;
+
+ /* if we can avoid processing samples, do so */
+ if (handle->downsampling_count != 1) {
+ if (handle->current_downsample < handle->downsampling_count) {
+ handle->current_downsample++;
+ return; /* throw this sample out */
+ }
+ handle->current_downsample = 1;
+ }
+
+ /* store sample in buffer */
+ handle->buffer[handle->ringstart++] = normalized_sample;
+ if (handle->ringstart >= handle->corrsize) {
+ handle->ringstart = 0;
+ }
+
+ /* do the correlation calculation */
+ factors[0] = factors[1] = factors[2] = factors[3] = 0; /* clear out intermediate sums */
+ j = handle->ringstart;
+ for (i = 0; i < handle->corrsize; i++) {
+ if (j >= handle->corrsize) {
+ j = 0;
+ }
+ val = handle->buffer[j];
+ factors[0] += handle->correlates[0][i] * val;
+ factors[1] += handle->correlates[1][i] * val;
+ factors[2] += handle->correlates[2][i] * val;
+ factors[3] += handle->correlates[3][i] * val;
+ j++;
+ }
+
+ /* store the bit (bit value is comparison of the two sets of correlate factors) */
+ handle->previous_bit = handle->current_bit;
+ handle->current_bit = (factors[0] * factors[0] + factors[1] * factors[1] > factors[2] * factors[2] + factors[3] * factors[3]);
+
+ /* if there's a transition, we can synchronize the cell position */
+ if (handle->previous_bit != handle->current_bit) {
+ handle->cellpos = 0.5; /* adjust cell position to be in the middle of the cell */
+ }
+ handle->cellpos += handle->celladj; /* walk the cell along */
+
+ if (handle->cellpos > 1.0) {
+ handle->cellpos -= 1.0;
+
+ switch (handle->state) {
+ case FSK_STATE_DATA:
+ {
+
+ (*handle->attr.bithandler) (handle->attr.bithandler_arg, handle->current_bit);
+ }
+ break;
+ case FSK_STATE_CHANSEIZE:
+ {
+
+ if (handle->last_bit != handle->current_bit) {
+ handle->conscutive_state_bits++;
+ } else {
+ handle->conscutive_state_bits = 0;
+ }
+
+ if (handle->conscutive_state_bits > 15) {
+ handle->state = FSK_STATE_CARRIERSIG;
+ handle->conscutive_state_bits = 0;
+ }
+ }
+ break;
+ case FSK_STATE_CARRIERSIG:
+ {
+ if (handle->current_bit) {
+ handle->conscutive_state_bits++;
+ } else {
+ handle->conscutive_state_bits = 0;
+ }
+
+ if (handle->conscutive_state_bits > 15) {
+ handle->state = FSK_STATE_DATA;
+ handle->conscutive_state_bits = 0;
+ }
+ }
+ break;
+ }
+
+ handle->last_bit = handle->current_bit;
+ }
+}
+
diff --git a/src/mod/applications/mod_fsk/fsk.h b/src/mod/applications/mod_fsk/fsk.h
new file mode 100644
index 0000000000..b098444d03
--- /dev/null
+++ b/src/mod/applications/mod_fsk/fsk.h
@@ -0,0 +1,113 @@
+/*
+ * bell202.h
+ *
+ * Copyright (c) 2005 Robert Krten. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * This module contains the manifest constants and declarations for
+ * the Bell-202 1200 baud FSK modem.
+ *
+ * 2005 03 20 R. Krten created
+*/
+
+#ifndef __FSK_H__
+#define __FSK_H__
+#include "uart.h"
+
+typedef struct {
+ int freq_space; /* Frequency of the 0 bit */
+ int freq_mark; /* Frequency of the 1 bit */
+ int baud_rate; /* baud rate for the modem */
+} fsk_modem_definition_t;
+
+/* Must be kept in sync with fsk_modem_definitions array in fsk.c */
+/* V.23 definitions: http://www.itu.int/rec/recommendation.asp?type=folders&lang=e&parent=T-REC-V.23 */
+typedef enum {
+ FSK_V23_FORWARD_MODE1 = 0, /* Maximum 600 bps for long haul */
+ FSK_V23_FORWARD_MODE2, /* Standard 1200 bps V.23 */
+ FSK_V23_BACKWARD, /* 75 bps return path for V.23 */
+ FSK_BELL202 /* Bell 202 half-duplex 1200 bps */
+} fsk_modem_types_t;
+
+typedef enum {
+ FSK_STATE_CHANSEIZE = 0,
+ FSK_STATE_CARRIERSIG,
+ FSK_STATE_DATA
+} fsk_state_t;
+
+typedef struct dsp_fsk_attr_s
+{
+ int sample_rate; /* sample rate in HZ */
+ bithandler_func_t bithandler; /* bit handler */
+ void *bithandler_arg; /* arbitrary ID passed to bithandler as first argument */
+ bytehandler_func_t bytehandler; /* byte handler */
+ void *bytehandler_arg; /* arbitrary ID passed to bytehandler as first argument */
+} dsp_fsk_attr_t;
+
+typedef struct
+{
+ fsk_state_t state;
+ dsp_fsk_attr_t attr; /* attributes structure */
+ double *correlates[4]; /* one for each of sin/cos for mark/space */
+ int corrsize; /* correlate size (also number of samples in ring buffer) */
+ double *buffer; /* sample ring buffer */
+ int ringstart; /* ring buffer start offset */
+ double cellpos; /* bit cell position */
+ double celladj; /* bit cell adjustment for each sample */
+ int previous_bit; /* previous bit (for detecting a transition to sync-up cell position) */
+ int current_bit; /* current bit */
+ int last_bit;
+ int downsampling_count; /* number of samples to skip */
+ int current_downsample; /* current skip count */
+ int conscutive_state_bits; /* number of bits in a row that matches the pattern for the current state */
+} dsp_fsk_handle_t;
+
+/*
+ * Function prototypes
+ *
+ * General calling order is:
+ * a) create the attributes structure (dsp_fsk_attr_init)
+ * b) initialize fields in the attributes structure (dsp_fsk_attr_set_*)
+ * c) create a Bell-202 handle (dsp_fsk_create)
+ * d) feed samples through the handler (dsp_fsk_sample)
+*/
+
+void dsp_fsk_attr_init(dsp_fsk_attr_t *attributes);
+
+bithandler_func_t dsp_fsk_attr_get_bithandler(dsp_fsk_attr_t *attributes, void **bithandler_arg);
+void dsp_fsk_attr_set_bithandler(dsp_fsk_attr_t *attributes, bithandler_func_t bithandler, void *bithandler_arg);
+bytehandler_func_t dsp_fsk_attr_get_bytehandler(dsp_fsk_attr_t *attributes, void **bytehandler_arg);
+void dsp_fsk_attr_set_bytehandler(dsp_fsk_attr_t *attributes, bytehandler_func_t bytehandler, void *bytehandler_arg);
+int dsp_fsk_attr_get_samplerate(dsp_fsk_attr_t *attributes);
+int dsp_fsk_attr_set_samplerate(dsp_fsk_attr_t *attributes, int samplerate);
+
+dsp_fsk_handle_t * dsp_fsk_create(dsp_fsk_attr_t *attributes);
+void dsp_fsk_destroy(dsp_fsk_handle_t **handle);
+
+void dsp_fsk_sample(dsp_fsk_handle_t *handle, double normalized_sample);
+
+extern fsk_modem_definition_t fsk_modem_definitions[];
+
+#endif
+
diff --git a/src/mod/applications/mod_fsk/fsk_callerid.c b/src/mod/applications/mod_fsk/fsk_callerid.c
new file mode 100644
index 0000000000..2146f663c5
--- /dev/null
+++ b/src/mod/applications/mod_fsk/fsk_callerid.c
@@ -0,0 +1,398 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * 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
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Anthony Minessale II
+ *
+ * mod_fsk -- FSK data transfer
+ *
+ */
+
+#include "switch.h"
+#include "fsk_callerid.h"
+
+void bitstream_init(bitstream_t *bsp, uint8_t *data, uint32_t datalen, endian_t endian, uint8_t ss)
+{
+ memset(bsp, 0, sizeof(*bsp));
+ bsp->data = data;
+ bsp->datalen = datalen;
+ bsp->endian = endian;
+ bsp->ss = ss;
+
+ if (endian < 0) {
+ bsp->top = bsp->bit_index = 7;
+ bsp->bot = 0;
+ } else {
+ bsp->top = bsp->bit_index = 0;
+ bsp->bot = 7;
+ }
+
+}
+
+int8_t bitstream_get_bit(bitstream_t *bsp)
+{
+ int8_t bit = -1;
+
+
+ if (bsp->byte_index >= bsp->datalen) {
+ goto done;
+ }
+
+ if (bsp->ss) {
+ if (!bsp->ssv) {
+ bsp->ssv = 1;
+ return 0;
+ } else if (bsp->ssv == 2) {
+ bsp->byte_index++;
+ bsp->ssv = 0;
+ return 1;
+ }
+ }
+
+ bit = (bsp->data[bsp->byte_index] >> (bsp->bit_index)) & 1;
+
+ if (bsp->bit_index == bsp->bot) {
+ bsp->bit_index = bsp->top;
+ if (bsp->ss) {
+ bsp->ssv = 2;
+ goto done;
+ }
+
+ if (++bsp->byte_index > bsp->datalen) {
+ bit = -1;
+ goto done;
+ }
+
+ } else {
+ bsp->bit_index = bsp->bit_index + bsp->endian;
+ }
+
+
+ done:
+ return bit;
+}
+
+
+
+static void fsk_byte_handler (void *x, int data)
+{
+ fsk_data_state_t *state = (fsk_data_state_t *) x;
+ uint8_t byte = (uint8_t)data;
+
+ top:
+
+ if (state->init == 3) {
+ return;
+ }
+
+ if (state->dlen) {
+ goto add_byte;
+ }
+
+ if (state->bpos == 1) {
+ state->blen = byte;
+
+ if ((uint32_t)(state->dlen = state->bpos + byte + 2) > state->bufsize) {
+ state->dlen = state->bufsize;
+ }
+ goto top;
+ }
+
+ add_byte:
+
+ if (state->bpos <= state->dlen) {
+ state->buf[state->bpos++] = byte;
+ } else {
+ state->init = 3;
+ }
+}
+
+switch_status_t fsk_data_init(fsk_data_state_t *state, uint8_t *data, uint32_t datalen)
+{
+ memset(state, 0, sizeof(*state));
+ state->buf = data;
+ state->bufsize = datalen;
+ state->bpos = 2;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t fsk_data_add_sdmf(fsk_data_state_t *state, const char *date, char *number)
+{
+ size_t dlen = strlen(date);
+ size_t nlen = strlen(number);
+
+ state->buf[0] = CID_TYPE_SDMF;
+ memcpy(&state->buf[state->bpos], date, dlen);
+ state->bpos += dlen;
+ memcpy(&state->buf[state->bpos], number, nlen);
+ state->bpos += nlen;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t fsk_data_add_mdmf(fsk_data_state_t *state, mdmf_type_t type, const uint8_t *data, uint32_t datalen)
+{
+ state->buf[0] = CID_TYPE_MDMF;
+ state->buf[state->bpos++] = type;
+ state->buf[state->bpos++] = (uint8_t)datalen;
+ memcpy(&state->buf[state->bpos], data, datalen);
+ state->bpos += datalen;
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+switch_status_t fsk_data_add_checksum(fsk_data_state_t *state)
+{
+ uint32_t i;
+ uint8_t check = 0;
+
+ state->buf[1] = (uint8_t)(state->bpos - 2);
+
+ for (i = 0; i < state->bpos; i++) {
+ check = check + state->buf[i];
+ }
+
+ state->checksum = state->buf[state->bpos] = (uint8_t)(256 - check);
+ state->bpos++;
+
+ state->dlen = state->bpos;
+ state->blen = state->buf[1];
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+switch_status_t fsk_data_parse(fsk_data_state_t *state, size_t *type, char **data, size_t *len)
+{
+
+ size_t i;
+ int sum = 0;
+
+ top:
+
+ if (state->checksum != 0 || state->ppos >= state->dlen - 1) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!state->ppos) {
+ for(i = 0; i < state->bpos; i++) {
+ sum += state->buf[i];
+ }
+ state->checksum = sum % 256;
+ state->ppos = 2;
+
+ if (state->buf[0] != CID_TYPE_MDMF && state->buf[0] != CID_TYPE_SDMF) {
+ state->checksum = -1;
+ }
+ goto top;
+ }
+
+ if (state->buf[0] == CID_TYPE_SDMF) {
+ /* convert sdmf to mdmf so we don't need 2 parsers */
+ if (state->ppos == 2) {
+ *type = MDMF_DATETIME;
+ *len = 8;
+ } else {
+ if (state->buf[state->ppos] == 'P' || state->buf[state->ppos] == 'O') {
+ *type = MDMF_NO_NUM;
+ *len = 1;
+ } else {
+ *type = MDMF_PHONE_NUM;
+ *len = state->blen - 8;
+ }
+ }
+ *data = (char *)&state->buf[state->ppos];
+ state->ppos += *len;
+ return SWITCH_STATUS_SUCCESS;
+ } else if (state->buf[0] == CID_TYPE_MDMF) {
+ *type = state->buf[state->ppos++];
+ *len = state->buf[state->ppos++];
+ *data = (char *)&state->buf[state->ppos];
+ state->ppos += *len;
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ return SWITCH_STATUS_FALSE;
+}
+
+switch_status_t fsk_demod_feed(fsk_data_state_t *state, int16_t *data, size_t samples)
+{
+ uint32_t x;
+ int16_t *sp = data;
+
+ if (state->init == 3) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ for (x = 0; x < samples; x++) {
+ dsp_fsk_sample (state->fsk1200_handle, (double) *sp++ / 32767.0);
+ if (state->dlen && state->bpos >= state->dlen) {
+ state->init = 3;
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t fsk_demod_destroy(fsk_data_state_t *state)
+{
+ dsp_fsk_destroy(&state->fsk1200_handle);
+ memset(state, 0, sizeof(*state));
+ return SWITCH_STATUS_SUCCESS;
+}
+
+int fsk_demod_init(fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize)
+{
+
+ dsp_fsk_attr_t fsk1200_attr;
+
+ if (state->fsk1200_handle) {
+ dsp_fsk_destroy(&state->fsk1200_handle);
+ }
+
+ memset(state, 0, sizeof(*state));
+ memset(buf, 0, bufsize);
+ state->buf = buf;
+ state->bufsize = bufsize;
+
+ dsp_fsk_attr_init (&fsk1200_attr);
+ dsp_fsk_attr_set_samplerate (&fsk1200_attr, rate);
+ dsp_fsk_attr_set_bytehandler (&fsk1200_attr, fsk_byte_handler, state);
+ state->fsk1200_handle = dsp_fsk_create (&fsk1200_attr);
+
+ if (state->fsk1200_handle == NULL) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+size_t fsk_modulator_generate_bit(fsk_modulator_t *fsk_trans, int8_t bit, int16_t *buf, size_t buflen)
+{
+ size_t i;
+
+ for(i = 0 ; i < buflen; i++) {
+ fsk_trans->bit_accum += fsk_trans->bit_factor;
+ if (fsk_trans->bit_accum >= FSK_MOD_FACTOR) {
+ fsk_trans->bit_accum -= (FSK_MOD_FACTOR + fsk_trans->bit_factor);
+ break;
+ }
+
+ buf[i] = teletone_dds_state_modulate_sample(&fsk_trans->dds, bit);
+ }
+
+ return i;
+}
+
+
+int32_t fsk_modulator_generate_carrier_bits(fsk_modulator_t *fsk_trans, uint32_t bits)
+{
+ uint32_t i = 0;
+ size_t r = 0;
+ int8_t bit = 1;
+
+ for (i = 0; i < bits; i++) {
+ if ((r = fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) {
+ if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != SWITCH_STATUS_SUCCESS) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ return i;
+}
+
+
+void fsk_modulator_generate_chan_sieze(fsk_modulator_t *fsk_trans)
+{
+ uint32_t i = 0;
+ size_t r = 0;
+ int8_t bit = 0;
+
+ for (i = 0; i < fsk_trans->chan_sieze_bits; i++) {
+ if ((r = fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) {
+ if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != SWITCH_STATUS_SUCCESS) {
+ break;
+ }
+ } else {
+ break;
+ }
+ bit = !bit;
+ }
+
+
+}
+
+
+void fsk_modulator_send_data(fsk_modulator_t *fsk_trans)
+{
+ size_t r = 0;
+ int8_t bit = 0;
+
+ while((bit = bitstream_get_bit(&fsk_trans->bs)) > -1) {
+ if ((r = fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) {
+ if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != SWITCH_STATUS_SUCCESS) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+}
+
+
+switch_status_t fsk_modulator_init(fsk_modulator_t *fsk_trans,
+ fsk_modem_types_t modem_type,
+ uint32_t sample_rate,
+ fsk_data_state_t *fsk_data,
+ float db_level,
+ uint32_t carrier_bits_start,
+ uint32_t carrier_bits_stop,
+ uint32_t chan_sieze_bits,
+ fsk_write_sample_t write_sample_callback,
+ void *user_data)
+{
+ memset(fsk_trans, 0, sizeof(*fsk_trans));
+ fsk_trans->modem_type = modem_type;
+ teletone_dds_state_set_tone(&fsk_trans->dds, fsk_modem_definitions[fsk_trans->modem_type].freq_space, sample_rate, 0);
+ teletone_dds_state_set_tone(&fsk_trans->dds, fsk_modem_definitions[fsk_trans->modem_type].freq_mark, sample_rate, 1);
+ fsk_trans->bit_factor = (uint32_t)((fsk_modem_definitions[fsk_trans->modem_type].baud_rate * FSK_MOD_FACTOR) / (float)sample_rate);
+ fsk_trans->samples_per_bit = (uint32_t) (sample_rate / fsk_modem_definitions[fsk_trans->modem_type].baud_rate);
+ fsk_trans->est_bytes = (int32_t)(((fsk_data->dlen * 10) + carrier_bits_start + carrier_bits_stop + chan_sieze_bits) * ((fsk_trans->samples_per_bit + 1) * 2));
+ fsk_trans->bit_accum = 0;
+ fsk_trans->fsk_data = fsk_data;
+ teletone_dds_state_set_tx_level(&fsk_trans->dds, db_level);
+ bitstream_init(&fsk_trans->bs, fsk_trans->fsk_data->buf, (uint32_t)fsk_trans->fsk_data->dlen, ENDIAN_BIG, 1);
+ fsk_trans->carrier_bits_start = carrier_bits_start;
+ fsk_trans->carrier_bits_stop = carrier_bits_stop;
+ fsk_trans->chan_sieze_bits = chan_sieze_bits;
+ fsk_trans->write_sample_callback = write_sample_callback;
+ fsk_trans->user_data = user_data;
+ return SWITCH_STATUS_SUCCESS;
+}
+
diff --git a/src/mod/applications/mod_fsk/fsk_callerid.h b/src/mod/applications/mod_fsk/fsk_callerid.h
new file mode 100644
index 0000000000..9018201ce5
--- /dev/null
+++ b/src/mod/applications/mod_fsk/fsk_callerid.h
@@ -0,0 +1,144 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * 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
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Anthony Minessale II
+ *
+ * mod_fsk -- FSK data transfer
+ *
+ */
+#ifndef __FSK_CALLER_ID_H
+#define __FSK_CALLER_ID_H
+SWITCH_BEGIN_EXTERN_C
+#include "fsk.h"
+#include "uart.h"
+
+#define FSK_MOD_FACTOR 0x10000
+
+typedef enum {
+ ENDIAN_BIG = 1,
+ ENDIAN_LITTLE = -1
+} endian_t;
+
+typedef enum {
+ CID_TYPE_SDMF = 0x04,
+ CID_TYPE_MDMF = 0x80
+} cid_type_t;
+
+typedef enum {
+ MDMF_DATETIME = 1,
+ MDMF_PHONE_NUM = 2,
+ MDMF_DDN = 3,
+ MDMF_NO_NUM = 4,
+ MDMF_PHONE_NAME = 7,
+ MDMF_NO_NAME = 8,
+ MDMF_ALT_ROUTE = 9,
+ MDMF_NAME_VALUE = 10,
+ MDMF_INVALID = 11
+} mdmf_type_t;
+
+struct bitstream {
+ uint8_t *data;
+ uint32_t datalen;
+ uint32_t byte_index;
+ uint8_t bit_index;
+ int8_t endian;
+ uint8_t top;
+ uint8_t bot;
+ uint8_t ss;
+ uint8_t ssv;
+};
+
+struct fsk_data_state {
+ dsp_fsk_handle_t *fsk1200_handle;
+ uint8_t init;
+ uint8_t *buf;
+ size_t bufsize;
+ size_t blen;
+ size_t bpos;
+ size_t dlen;
+ size_t ppos;
+ int checksum;
+};
+
+typedef struct bitstream bitstream_t;
+typedef struct fsk_data_state fsk_data_state_t;
+typedef switch_status_t (*fsk_write_sample_t)(int16_t *buf, size_t buflen, void *user_data);
+
+struct fsk_modulator {
+ teletone_dds_state_t dds;
+ bitstream_t bs;
+ uint32_t carrier_bits_start;
+ uint32_t carrier_bits_stop;
+ uint32_t chan_sieze_bits;
+ uint32_t bit_factor;
+ uint32_t bit_accum;
+ uint32_t sample_counter;
+ int32_t samples_per_bit;
+ int32_t est_bytes;
+ fsk_modem_types_t modem_type;
+ fsk_data_state_t *fsk_data;
+ fsk_write_sample_t write_sample_callback;
+ void *user_data;
+ int16_t sample_buffer[64];
+};
+
+
+typedef int (*fsk_data_decoder_t)(fsk_data_state_t *state);
+
+typedef void (*logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...);
+typedef struct fsk_modulator fsk_modulator_t;
+
+switch_status_t fsk_data_init(fsk_data_state_t *state, uint8_t *data, uint32_t datalen);
+void bitstream_init(bitstream_t *bsp, uint8_t *data, uint32_t datalen, endian_t endian, uint8_t ss);
+int8_t bitstream_get_bit(bitstream_t *bsp);
+switch_status_t fsk_data_add_mdmf(fsk_data_state_t *state, mdmf_type_t type, const uint8_t *data, uint32_t datalen);
+switch_status_t fsk_data_add_checksum(fsk_data_state_t *state);
+switch_status_t fsk_data_parse(fsk_data_state_t *state, size_t *type, char **data, size_t *len);
+switch_status_t fsk_demod_feed(fsk_data_state_t *state, int16_t *data, size_t samples);
+switch_status_t fsk_demod_destroy(fsk_data_state_t *state);
+int fsk_demod_init(fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize);
+size_t fsk_modulator_generate_bit(fsk_modulator_t *fsk_trans, int8_t bit, int16_t *buf, size_t buflen);
+int32_t fsk_modulator_generate_carrier_bits(fsk_modulator_t *fsk_trans, uint32_t bits);
+void fsk_modulator_generate_chan_sieze(fsk_modulator_t *fsk_trans);
+void fsk_modulator_send_data(fsk_modulator_t *fsk_trans);
+switch_status_t fsk_modulator_init(fsk_modulator_t *fsk_trans,
+ fsk_modem_types_t modem_type,
+ uint32_t sample_rate,
+ fsk_data_state_t *fsk_data,
+ float db_level,
+ uint32_t carrier_bits_start,
+ uint32_t carrier_bits_stop,
+ uint32_t chan_sieze_bits,
+ fsk_write_sample_t write_sample_callback,
+ void *user_data);
+
+
+#define fsk_modulator_send_all(_it) fsk_modulator_generate_chan_sieze(_it); \
+ fsk_modulator_generate_carrier_bits(_it, _it->carrier_bits_start); \
+ fsk_modulator_send_data(_it); \
+ fsk_modulator_generate_carrier_bits(_it, _it->carrier_bits_stop)
+
+SWITCH_END_EXTERN_C
+#endif
diff --git a/src/mod/applications/mod_fsk/mod_fsk.c b/src/mod/applications/mod_fsk/mod_fsk.c
new file mode 100644
index 0000000000..9802353075
--- /dev/null
+++ b/src/mod/applications/mod_fsk/mod_fsk.c
@@ -0,0 +1,486 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * 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
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Anthony Minessale II
+ *
+ * mod_fsk.c -- FSK data transfer
+ *
+ */
+#include
+#include "fsk_callerid.h"
+
+/* Prototypes */
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fsk_shutdown);
+SWITCH_MODULE_RUNTIME_FUNCTION(mod_fsk_runtime);
+SWITCH_MODULE_LOAD_FUNCTION(mod_fsk_load);
+
+/* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime)
+ * Defines a switch_loadable_module_function_table_t and a static const char[] modname
+ */
+SWITCH_MODULE_DEFINITION(mod_fsk, mod_fsk_load, mod_fsk_shutdown, NULL);
+
+switch_status_t my_write_sample(int16_t *buf, size_t buflen, void *user_data)
+{
+ switch_buffer_t *buffer = (switch_buffer_t *) user_data;
+
+ switch_buffer_write(buffer, buf, buflen * 2);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t write_fsk_data(uint32_t rate, int32_t db, switch_buffer_t *buffer, switch_event_t *event, const char *prefix)
+{
+ fsk_modulator_t fsk_trans;
+ fsk_data_state_t fsk_data = {0};
+ uint8_t databuf[1024] = "";
+ char time_str[9];
+ struct tm tm;
+ time_t now;
+ switch_event_header_t *hp;
+ switch_size_t plen = 0;
+
+ memset(&fsk_trans, 0, sizeof(fsk_trans));
+
+ time(&now);
+ localtime_r(&now, &tm);
+ strftime(time_str, sizeof(time_str), "%m%d%H%M", &tm);
+
+ fsk_data_init(&fsk_data, databuf, sizeof(databuf));
+ fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, (uint8_t *)time_str, strlen(time_str));
+
+ if (prefix) {
+ plen = strlen(prefix);
+ }
+
+
+ if (event) {
+ for (hp = event->headers; hp; hp = hp->next) {
+ char *packed;
+ char *name = hp->name;
+
+ if (plen && strncasecmp(name, prefix, plen)) {
+ continue;
+ }
+
+ name += plen;
+
+ if (zstr(name)) {
+ continue;
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Encoding [%s][%s]\n", hp->name, hp->value);
+
+ if (!strcasecmp(name, "phone_num")) {
+ fsk_data_add_mdmf(&fsk_data, MDMF_PHONE_NUM, (uint8_t *)hp->value, strlen(hp->value));
+ } else if (!strcasecmp(name, "phone_name")) {
+ fsk_data_add_mdmf(&fsk_data, MDMF_PHONE_NAME, (uint8_t *)hp->value, strlen(hp->value));
+ } else {
+ packed = switch_mprintf("%q:%q", name, hp->value);
+ fsk_data_add_mdmf(&fsk_data, MDMF_NAME_VALUE, (uint8_t *)packed, strlen(packed));
+ free(packed);
+ }
+ }
+ }
+
+ fsk_data_add_checksum(&fsk_data);
+
+ fsk_modulator_init(&fsk_trans, FSK_BELL202, rate, &fsk_data, db, 180, 5, 300, my_write_sample, buffer);
+ fsk_modulator_send_all((&fsk_trans));
+
+ fsk_demod_destroy(&fsk_data);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+SWITCH_STANDARD_APP(fsk_send_function) {
+ switch_event_t *event = NULL;
+ switch_buffer_t *buffer;
+ switch_slin_data_t sdata = { 0 };
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_frame_t *read_frame;
+ switch_status_t status;
+
+
+ if (data) {
+ switch_ivr_sleep(session, 1000, SWITCH_TRUE, NULL);
+ switch_core_session_send_dtmf_string(session, (const char *) data);
+ switch_ivr_sleep(session, 1500, SWITCH_TRUE, NULL);
+ }
+
+ if (switch_core_session_set_codec_slin(session, &sdata) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
+ SWITCH_LOG_ERROR, "FAILURE\n");
+ return;
+ }
+
+ switch_buffer_create_dynamic(&buffer, 1024, 2048, 0);
+
+ switch_channel_get_variables(channel, &event);
+
+ write_fsk_data(sdata.codec.implementation->actual_samples_per_second, -14, buffer, event, "fsk_");
+
+ while(switch_channel_ready(channel)) {
+ status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
+
+ if (!SWITCH_READ_ACCEPTABLE(status)) {
+ break;
+ }
+
+ if ((sdata.write_frame.datalen = switch_buffer_read(buffer, sdata.write_frame.data,
+ sdata.codec.implementation->decoded_bytes_per_packet)) <= 0) {
+ break;
+ }
+
+
+ if (sdata.write_frame.datalen < sdata.codec.implementation->decoded_bytes_per_packet) {
+ memset((char *)sdata.write_frame.data + sdata.write_frame.datalen, 255,
+ sdata.codec.implementation->decoded_bytes_per_packet - sdata.write_frame.datalen);
+ sdata.write_frame.datalen = sdata.codec.implementation->decoded_bytes_per_packet;
+ }
+ sdata.write_frame.samples = sdata.write_frame.datalen / 2;
+ switch_core_session_write_frame(sdata.session, &sdata.write_frame, SWITCH_IO_FLAG_NONE, 0);
+ }
+
+ switch_buffer_destroy(&buffer);
+ switch_core_codec_destroy(&sdata.codec);
+ switch_core_session_set_read_codec(session, NULL);
+
+}
+
+typedef struct {
+ switch_core_session_t *session;
+ fsk_data_state_t fsk_data;
+ uint8_t fbuf[512];
+ int skip;
+} switch_fsk_detect_t;
+
+
+
+
+static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
+{
+ switch_fsk_detect_t *pvt = (switch_fsk_detect_t *) user_data;
+ //switch_frame_t *frame = NULL;
+ switch_channel_t *channel = switch_core_session_get_channel(pvt->session);
+
+ switch (type) {
+ case SWITCH_ABC_TYPE_INIT: {
+ switch_codec_implementation_t read_impl = { 0 };
+ switch_core_session_get_read_impl(pvt->session, &read_impl);
+
+ if (fsk_demod_init(&pvt->fsk_data, read_impl.actual_samples_per_second, pvt->fbuf, sizeof(pvt->fbuf))) {
+ return SWITCH_FALSE;
+ }
+
+ break;
+ }
+ case SWITCH_ABC_TYPE_CLOSE:
+ {
+ fsk_demod_destroy(&pvt->fsk_data);
+ }
+ break;
+
+ case SWITCH_ABC_TYPE_WRITE_REPLACE:
+ case SWITCH_ABC_TYPE_READ_REPLACE:
+ {
+ switch_frame_t *rframe;
+
+ if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
+ rframe = switch_core_media_bug_get_read_replace_frame(bug);
+ } else {
+ rframe = switch_core_media_bug_get_write_replace_frame(bug);
+ }
+
+ if (!pvt->skip && fsk_demod_feed(&pvt->fsk_data, rframe->data, rframe->datalen / 2) != SWITCH_STATUS_SUCCESS) {
+ char str[1024] = "";
+ size_t type, mlen;
+ char *sp;
+ switch_event_t *event;
+ const char *app_var;
+
+ switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA);
+
+ while(fsk_data_parse(&pvt->fsk_data, &type, &sp, &mlen) == SWITCH_STATUS_SUCCESS) {
+ char *varname = NULL, *val, *p;
+
+ switch_copy_string(str, sp, mlen+1);
+ *(str+mlen) = '\0';
+ switch_clean_string(str);
+ //printf("TYPE %u LEN %u VAL [%s]\n", (unsigned)type, (unsigned)mlen, str);
+
+ val = str;
+
+ switch(type) {
+ case MDMF_DATETIME:
+ varname = "fsk_datetime";
+ break;
+ case MDMF_PHONE_NAME:
+ varname = "fsk_phone_name";
+ break;
+ case MDMF_PHONE_NUM:
+ varname = "fsk_phone_num";
+ break;
+ case MDMF_NAME_VALUE:
+ varname = switch_core_session_sprintf(pvt->session, "fsk_%s", val);
+ if ((p = strchr(varname, ':'))) {
+ *p++ = '\0';
+ val = p;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (varname && val) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s setting FSK var [%s][%s]\n",
+ switch_channel_get_name(channel), varname, val);
+ switch_channel_set_variable(channel, varname, val);
+ if (event) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, varname, val);
+ }
+ }
+ }
+
+ if (event) {
+ if (switch_core_session_queue_event(pvt->session, &event) != SWITCH_STATUS_SUCCESS) {
+ switch_event_destroy(&event);
+ }
+ }
+
+ if ((app_var = switch_channel_get_variable(channel, "execute_on_fsk"))) {
+ char *app_arg;
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s processing execute_on_fsk [%s]\n",
+ switch_channel_get_name(channel), app_var);
+ if ((app_arg = strchr(app_var, ' '))) {
+ *app_arg++ = '\0';
+ }
+ switch_core_session_execute_application(pvt->session, app_var, app_arg);
+ }
+
+ pvt->skip = 10;
+ }
+
+ memset(rframe->data, 255, rframe->datalen);
+
+ if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
+ switch_core_media_bug_set_read_replace_frame(bug, rframe);
+ } else {
+ switch_core_media_bug_set_write_replace_frame(bug, rframe);
+ }
+
+ if (pvt->skip && !--pvt->skip) {
+ return SWITCH_FALSE;
+ }
+
+ }
+ break;
+ case SWITCH_ABC_TYPE_WRITE:
+ default:
+ break;
+ }
+
+ return SWITCH_TRUE;
+}
+
+switch_status_t stop_fsk_detect_session(switch_core_session_t *session)
+{
+ switch_media_bug_t *bug;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+ if ((bug = switch_channel_get_private(channel, "fsk"))) {
+ switch_channel_set_private(channel, "fsk", NULL);
+ switch_core_media_bug_remove(session, &bug);
+ return SWITCH_STATUS_SUCCESS;
+ }
+ return SWITCH_STATUS_FALSE;
+}
+
+switch_status_t fsk_detect_session(switch_core_session_t *session, const char *flags)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_media_bug_t *bug;
+ switch_status_t status;
+ switch_fsk_detect_t *pvt = { 0 };
+ switch_codec_implementation_t read_impl = { 0 };
+ int bflags = SMBF_READ_REPLACE;
+
+ if (strchr(flags, 'w')) {
+ bflags = SMBF_WRITE_REPLACE;
+ }
+
+ switch_core_session_get_read_impl(session, &read_impl);
+
+ if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
+ return SWITCH_STATUS_MEMERR;
+ }
+
+ pvt->session = session;
+
+
+ if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if ((status = switch_core_media_bug_add(session, "fsk_detect", NULL,
+ fsk_detect_callback, pvt, 0, bflags | SMBF_NO_PAUSE, &bug)) != SWITCH_STATUS_SUCCESS) {
+ return status;
+ }
+
+ switch_channel_set_private(channel, "fsk", bug);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+SWITCH_STANDARD_APP(fsk_recv_function)
+{
+ fsk_detect_session(session, data);
+}
+
+SWITCH_STANDARD_APP(fsk_display_function)
+{
+ /* expected to be called via 'execute_on_fsk' -- passes display update over FSK */
+
+ const char *cid_name, *cid_num;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_core_session_message_t *msg;
+ switch_core_session_t *psession, *usession = NULL;
+ char *flags = (char *) data;
+
+ cid_name = switch_channel_get_variable(channel, "fsk_phone_name");
+ cid_num = switch_channel_get_variable(channel, "fsk_phone_num");
+
+ if (zstr(cid_name)) {
+ cid_name = cid_num;
+ }
+
+ if (zstr(cid_num)) {
+ return;
+ }
+
+ if (strchr(flags, 'b')) {
+ if (switch_core_session_get_partner(session, &psession) == SWITCH_STATUS_SUCCESS) {
+ usession = psession;
+ }
+ }
+
+ if (!usession) {
+ usession = session;
+ }
+
+ msg = switch_core_session_alloc(usession, sizeof(*msg));
+ MESSAGE_STAMP_FFL(msg);
+ msg->message_id = SWITCH_MESSAGE_INDICATE_DISPLAY;
+ msg->string_array_arg[0] = switch_core_session_strdup(usession, cid_name);
+ msg->string_array_arg[1] = switch_core_session_strdup(usession, cid_num);
+ msg->from = __FILE__;
+ switch_core_session_queue_message(usession, msg);
+
+ if (psession) {
+ switch_core_session_rwunlock(psession);
+ psession = NULL;
+ }
+}
+
+SWITCH_STANDARD_APP(fsk_simplify_function)
+{
+ /* expected to be called via 'execute_on_fsk' -- redirects call to point-to-point and eliminates legs in the middle */
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char *sip_uri, *fsk_simplify_profile, *fsk_simplify_context;
+ char *bridgeto;
+
+ if (!(sip_uri = switch_channel_get_variable(channel, "fsk_uri"))) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s Missing URI field!\n", switch_channel_get_name(channel));
+ }
+
+ if (!(fsk_simplify_profile = switch_channel_get_variable(channel, "fsk_simplify_profile"))) {
+ fsk_simplify_profile = "internal";
+ }
+
+ fsk_simplify_context = switch_channel_get_variable(channel, "fsk_simplify_context");
+
+ if (!zstr(sip_uri)) {
+ switch_core_session_t *psession;
+ switch_channel_t *pchannel;
+
+ bridgeto = switch_core_session_sprintf(session, "bridge:sofia/%s/sip:%s", fsk_simplify_profile, sip_uri);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s transfering to [%s]\n",
+ switch_channel_get_name(channel), bridgeto);
+
+
+ if (switch_core_session_get_partner(session, &psession) == SWITCH_STATUS_SUCCESS) {
+ pchannel = switch_core_session_get_channel(psession);
+ switch_channel_set_flag(pchannel, CF_REDIRECT);
+ switch_channel_set_flag(pchannel, CF_TRANSFER);
+ }
+
+ switch_ivr_session_transfer(session, bridgeto, "inline", fsk_simplify_context);
+
+ if (psession) {
+ switch_ivr_session_transfer(psession, "sleep:5000", "inline", NULL);
+ switch_core_session_rwunlock(psession);
+ }
+ }
+}
+
+/* Macro expands to: switch_status_t mod_fsk_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
+SWITCH_MODULE_LOAD_FUNCTION(mod_fsk_load)
+{
+ switch_application_interface_t *app_interface;
+
+ /* connect my internal structure to the blank pointer passed to me */
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+
+ SWITCH_ADD_APP(app_interface, "fsk_send", "fsk_send", NULL, fsk_send_function, NULL, SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "fsk_recv", "fsk_recv", NULL, fsk_recv_function, NULL, SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "fsk_simplify", "fsk_simplify", NULL, fsk_simplify_function, NULL, SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "fsk_display", "fsk_display", NULL, fsk_display_function, NULL, SAF_NONE);
+
+ /* indicate that the module should continue to be loaded */
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/*
+ Called when the system shuts down
+ Macro expands to: switch_status_t mod_fsk_shutdown() */
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fsk_shutdown)
+{
+ /* Cleanup dynamically allocated config settings */
+
+ 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
+ */
diff --git a/src/mod/applications/mod_fsk/uart.c b/src/mod/applications/mod_fsk/uart.c
new file mode 100644
index 0000000000..5e0dd85350
--- /dev/null
+++ b/src/mod/applications/mod_fsk/uart.c
@@ -0,0 +1,124 @@
+
+/*
+ * uart.c
+ *
+ * Copyright (c) 2005 Robert Krten. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * This module contains a simple 8-bit UART, which performs a callback
+ * with the decoded byte value.
+ *
+ * 2005 06 11 R. Krten created
+*/
+
+#include
+#include
+#include
+#include
+
+#include "uart.h"
+
+/*
+ * dsp_uart_attr_init
+ *
+ * Initializes the attributes structure; this must be done before the
+ * attributes structure is used.
+*/
+
+void dsp_uart_attr_init (dsp_uart_attr_t *attr)
+{
+ memset (attr, 0, sizeof (*attr));
+}
+
+/*
+ * dsp_uart_attr_get_bytehandler
+ * dsp_uart_attr_set_bytehandler
+ *
+ * These functions get and set their respective elements from the
+ * attributes structure. If an error code is returned, it is just
+ * zero == ok, -1 == fail.
+*/
+
+bytehandler_func_t dsp_uart_attr_get_bytehandler(dsp_uart_attr_t *attr, void **bytehandler_arg)
+{
+ *bytehandler_arg = attr->bytehandler_arg;
+ return attr->bytehandler;
+}
+
+void dsp_uart_attr_set_bytehandler(dsp_uart_attr_t *attr, bytehandler_func_t bytehandler, void *bytehandler_arg)
+{
+ attr->bytehandler = bytehandler;
+ attr->bytehandler_arg = bytehandler_arg;
+}
+
+dsp_uart_handle_t *dsp_uart_create(dsp_uart_attr_t *attr)
+{
+ dsp_uart_handle_t *handle;
+
+ handle = malloc(sizeof (*handle));
+ if (handle) {
+ memset(handle, 0, sizeof (*handle));
+
+ /* fill the attributes member */
+ memcpy(&handle->attr, attr, sizeof (*attr));
+ }
+ return handle;
+}
+
+void dsp_uart_destroy(dsp_uart_handle_t **handle)
+{
+ if (*handle) {
+ free(*handle);
+ *handle = NULL;
+ }
+}
+
+
+void dsp_uart_bit_handler(void *x, int bit)
+{
+ dsp_uart_handle_t *handle = (dsp_uart_handle_t *) x;
+
+ if (!handle->have_start) {
+ if (bit) {
+ return; /* waiting for start bit (0) */
+ }
+ handle->have_start = 1;
+ handle->data = 0;
+ handle->nbits = 0;
+ return;
+ }
+
+ handle->data >>= 1;
+ handle->data |= 0x80 * !!bit;
+ handle->nbits++;
+
+ if (handle->nbits == 8) {
+ handle->attr.bytehandler(handle->attr.bytehandler_arg, handle->data);
+ handle->nbits = 0;
+ handle->data = 0;
+ handle->have_start = 0;
+ }
+/* might consider handling errors in the future... */
+}
+
diff --git a/src/mod/applications/mod_fsk/uart.h b/src/mod/applications/mod_fsk/uart.h
new file mode 100644
index 0000000000..89c3a13abc
--- /dev/null
+++ b/src/mod/applications/mod_fsk/uart.h
@@ -0,0 +1,76 @@
+/*
+ * uart.h
+ *
+ * Copyright (c) 2005 Robert Krten. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * This module contains the manifest constants and declarations for
+ * the UART module.
+ *
+ * 2005 06 19 R. Krten created
+*/
+
+#ifndef __UART_H__
+#define __UART_H__
+
+typedef void (*bytehandler_func_t) (void *, int);
+typedef void (*bithandler_func_t) (void *, int);
+
+
+typedef struct dsp_uart_attr_s
+{
+ bytehandler_func_t bytehandler; /* byte handler */
+ void *bytehandler_arg; /* arbitrary ID passed to bytehandler as first argument */
+} dsp_uart_attr_t;
+
+typedef struct
+{
+ dsp_uart_attr_t attr;
+ int have_start; /* wait for start bit to show up */
+ int data; /* data buffer */
+ int nbits; /* number of bits accumulated so far */
+} dsp_uart_handle_t;
+
+/*
+ * Function prototypes
+ *
+ * General calling order is:
+ * a) create the attributes structure (dsp_uart_attr_init)
+ * b) initialize fields in the attributes structure (dsp_uart_attr_set_*)
+ * c) create a Bell-202 handle (dsp_uart_create)
+ * d) feed bits through dsp_uart_bit_handler
+*/
+
+void dsp_uart_attr_init(dsp_uart_attr_t *attributes);
+
+bytehandler_func_t dsp_uart_attr_get_bytehandler(dsp_uart_attr_t *attributes, void **bytehandler_arg);
+void dsp_uart_attr_set_bytehandler(dsp_uart_attr_t *attributes, bytehandler_func_t bytehandler, void *bytehandler_arg);
+
+dsp_uart_handle_t * dsp_uart_create(dsp_uart_attr_t *attributes);
+void dsp_uart_destroy(dsp_uart_handle_t **handle);
+
+void dsp_uart_bit_handler(void *handle, int bit);
+
+#endif
+
diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index 69dd217ca2..1799e5c7dc 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -1973,12 +1973,22 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
TRY_CODE(switch_ivr_phrase_macro(session, VM_CHOOSE_GREETING_FAIL_MACRO, NULL, NULL, NULL));
} else {
+ switch_event_t *params;
+
TRY_CODE(switch_ivr_phrase_macro(session, VM_CHOOSE_GREETING_SELECTED_MACRO, input, NULL, NULL));
sql =
switch_mprintf("update voicemail_prefs set greeting_path='%s' where username='%s' and domain='%s'", file_path, myid,
domain_name);
vm_execute_sql(profile, sql, profile->mutex);
switch_safe_free(sql);
+
+ switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Action", "change-greeting");
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Greeting-Path", file_path);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User", myid);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Domain", domain_name);
+ switch_channel_event_set_data(channel, params);
+ switch_event_fire(¶ms);
}
switch_safe_free(file_path);
} else if (!strcmp(input, profile->record_greeting_key)) {
@@ -1989,6 +1999,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
if (num < 1 || num > VM_MAX_GREETINGS) {
TRY_CODE(switch_ivr_phrase_macro(session, VM_CHOOSE_GREETING_FAIL_MACRO, NULL, NULL, NULL));
} else {
+ switch_event_t *params;
file_path = switch_mprintf("%s%sgreeting_%d.%s", dir_path, SWITCH_PATH_SEPARATOR, num, profile->file_ext);
TRY_CODE(create_file(session, profile, VM_RECORD_GREETING_MACRO, file_path, &message_len, SWITCH_TRUE, NULL, NULL));
sql =
@@ -1997,6 +2008,14 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
vm_execute_sql(profile, sql, profile->mutex);
switch_safe_free(sql);
switch_safe_free(file_path);
+
+ switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Action", "record-greeting");
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Greeting-Path", file_path);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User", myid);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Domain", domain_name);
+ switch_channel_event_set_data(channel, params);
+ switch_event_fire(¶ms);
}
} else if (!strcmp(input, profile->change_pass_key)) {
@@ -2027,12 +2046,21 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
switch_event_fire(¶ms);
} else if (!strcmp(input, profile->record_name_key)) {
+ switch_event_t *params;
file_path = switch_mprintf("%s%srecorded_name.%s", dir_path, SWITCH_PATH_SEPARATOR, profile->file_ext);
TRY_CODE(create_file(session, profile, VM_RECORD_NAME_MACRO, file_path, &message_len, SWITCH_FALSE, NULL, NULL));
sql = switch_mprintf("update voicemail_prefs set name_path='%s' where username='%s' and domain='%s'", file_path, myid, domain_name);
vm_execute_sql(profile, sql, profile->mutex);
switch_safe_free(file_path);
switch_safe_free(sql);
+
+ switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Action", "record-name");
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Name-Path", file_path);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User", myid);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Domain", domain_name);
+ switch_channel_event_set_data(channel, params);
+ switch_event_fire(¶ms);
}
continue;
}
@@ -2337,6 +2365,7 @@ static switch_status_t deliver_vm(vm_profile_t *profile,
const char *filename;
switch_xml_t x_param, x_params;
char *vm_email = NULL;
+ char *vm_email_from = NULL;
char *vm_notify_email = NULL;
char *email_addr = NULL;
char *vm_timezone = NULL;
@@ -2401,6 +2430,8 @@ static switch_status_t deliver_vm(vm_profile_t *profile,
vm_email = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "vm-notify-mailto")) {
vm_notify_email = switch_core_strdup(pool, val);
+ } else if (!strcasecmp(var, "vm-mailfrom")) {
+ vm_email_from = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "email-addr")) {
email_addr = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "vm-email-all-messages") && (send_main = switch_true(val))) {
@@ -2544,7 +2575,9 @@ static switch_status_t deliver_vm(vm_profile_t *profile,
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_message_len", duration_str);
- if (zstr(profile->email_from)) {
+ if (!zstr(vm_email_from)) {
+ from = switch_core_strdup(pool, vm_email_from);
+ } else if (zstr(profile->email_from)) {
from = switch_core_sprintf(pool, "%s@%s", myid, domain_name);
} else {
from = switch_event_expand_headers(params, profile->email_from);
diff --git a/src/mod/codecs/mod_ilbc/mod_ilbc.c b/src/mod/codecs/mod_ilbc/mod_ilbc.c
index 4d52ba9944..23ca642c22 100644
--- a/src/mod/codecs/mod_ilbc/mod_ilbc.c
+++ b/src/mod/codecs/mod_ilbc/mod_ilbc.c
@@ -163,7 +163,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_ilbc_load)
"mode=30", /* default fmtp to send (can be overridden by the init function) */
8000, /* samples transferred per second */
8000, /* actual samples transferred per second */
- 13300, /* bits transferred per second */
+ 13330, /* bits transferred per second */
30000, /* number of microseconds per frame */
ILBC_BLOCK_LEN_30MS, /* number of samples per frame */
ILBC_BLOCK_LEN_30MS * 2, /* number of bytes per frame decompressed */
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h
index df267967fa..b6ce97dac6 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.h
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.h
@@ -403,6 +403,7 @@ struct sofia_gateway {
char *register_from;
char *register_contact;
char *extension;
+ char *real_extension;
char *register_to;
char *register_proxy;
char *register_sticky_proxy;
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index 2643ceb17f..904f3ecb46 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -161,6 +161,15 @@ static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip, swit
char *full;
if (sip) {
+ if (sip->sip_route) {
+ if ((full = sip_header_as_string(profile->home, (void *) sip->sip_route))) {
+ const char *v = switch_channel_get_variable(channel, "sip_full_route");
+ if (!v) {
+ switch_channel_set_variable(channel, "sip_full_route", full);
+ }
+ su_free(profile->home, full);
+ }
+ }
if (sip->sip_via) {
if ((full = sip_header_as_string(profile->home, (void *) sip->sip_via))) {
const char *v = switch_channel_get_variable(channel, "sip_full_via");
@@ -2056,10 +2065,6 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
from_user = username;
}
- if (zstr(extension)) {
- extension = username;
- }
-
if (zstr(proxy)) {
proxy = realm;
}
@@ -2151,8 +2156,13 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
sipip = profile->sipip;
}
- gateway->extension = switch_core_strdup(gateway->pool, extension);
+ if (zstr(extension)) {
+ extension = username;
+ } else {
+ gateway->real_extension = switch_core_strdup(gateway->pool, extension);
+ }
+ gateway->extension = switch_core_strdup(gateway->pool, extension);
if (!strncasecmp(proxy, "sip:", 4)) {
gateway->register_proxy = switch_core_strdup(gateway->pool, proxy);
@@ -6222,6 +6232,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
char acl_token[512] = "";
sofia_transport_t transport;
const char *gw_name = NULL;
+ const char *gw_param_name = NULL;
char *call_info_str = NULL;
nua_handle_t *bnh = NULL;
char sip_acl_authed_by[512] = "";
@@ -6854,7 +6865,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
if (sip->sip_request->rq_url->url_params) {
- gw_name = sofia_glue_find_parameter_value(session, sip->sip_request->rq_url->url_params, "gw=");
+ gw_param_name = sofia_glue_find_parameter_value(session, sip->sip_request->rq_url->url_params, "gw=");
}
if (strstr(destination_number, "gw+")) {
@@ -6869,19 +6880,35 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
}
}
- if (gw_name) {
- sofia_gateway_t *gateway;
- if (gw_name && (gateway = sofia_reg_find_gateway(gw_name))) {
+ if (gw_name || gw_param_name) {
+ sofia_gateway_t *gateway = NULL;
+ char *extension = NULL;
+
+ if (gw_name && ((gateway = sofia_reg_find_gateway(gw_name)))) {
+ gw_param_name = NULL;
+ extension = gateway->extension;
+ }
+
+ if (!gateway && gw_param_name) {
+ gateway = sofia_reg_find_gateway(gw_param_name);
+ extension = gateway->real_extension;
+ }
+
+ if (gateway) {
context = switch_core_session_strdup(session, gateway->register_context);
switch_channel_set_variable(channel, "sip_gateway", gateway->name);
- if (gateway->extension) {
- if (!strcasecmp(gateway->extension, "auto_to_user")) {
+ if (!zstr(extension)) {
+ if (!strcasecmp(extension, "auto_to_user")) {
destination_number = sip->sip_to->a_url->url_user;
+ } else if (!strcasecmp(extension, "auto")) {
+ if (gw_name) {
+ destination_number = sip->sip_to->a_url->url_user;
+ }
} else {
- destination_number = switch_core_session_strdup(session, gateway->extension);
+ destination_number = switch_core_session_strdup(session, extension);
}
- } else {
+ } else if (!gw_param_name) {
destination_number = sip->sip_to->a_url->url_user;
}
diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c
index 715b70f59d..a529844059 100644
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -3550,13 +3550,53 @@ void sofia_glue_set_r_sdp_codec_string(switch_core_session_t *session, const cha
}
if (match) {
- if (ptime > 0) {
- switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh@%di", imp->iananame, (unsigned int) map->rm_rate,
- ptime);
- } else {
- switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh", imp->iananame, (unsigned int) map->rm_rate);
+ int codec_ms = ptime;
+ uint32_t map_bit_rate = 0;
+ char ptstr[20] = "";
+ char ratestr[20] = "";
+ char bitstr[20] = "";
+ switch_codec_fmtp_t codec_fmtp = { 0 };
+
+ if (!codec_ms) {
+ codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt);
}
- already_did[imp->ianacode] = 1;
+
+ map_bit_rate = switch_known_bitrate(map->rm_pt);
+
+ if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
+ ptime = codec_ms = 30;
+ }
+
+ if (zstr(map->rm_fmtp)) {
+ if (!strcasecmp(map->rm_encoding, "ilbc")) {
+ ptime = codec_ms = 30;
+ map_bit_rate = 13330;
+ }
+ } else {
+ if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
+ if (codec_fmtp.bits_per_second) {
+ map_bit_rate = codec_fmtp.bits_per_second;
+ }
+ if (codec_fmtp.microseconds_per_packet) {
+ codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
+ }
+ }
+ }
+
+ if (map->rm_rate) {
+ switch_snprintf(ratestr, sizeof(ratestr), "@%uh", (unsigned int) map->rm_rate);
+ }
+
+ if (codec_ms) {
+ switch_snprintf(ptstr, sizeof(ptstr), "@%di", codec_ms);
+ }
+
+ if (map_bit_rate) {
+ switch_snprintf(bitstr, sizeof(bitstr), "@%db", map_bit_rate);
+ }
+
+ switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s%s%s%s", map->rm_encoding, ratestr, ptstr, bitstr);
+
break;
}
}
@@ -4378,6 +4418,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
if (zstr(map->rm_fmtp)) {
if (!strcasecmp(map->rm_encoding, "ilbc")) {
ptime = codec_ms = 30;
+ map_bit_rate = 13330;
}
} else {
if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
@@ -4389,8 +4430,6 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
}
}
}
-
-
for (i = first; i < last && i < tech_pvt->num_codecs; i++) {
const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
@@ -4401,7 +4440,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d:%u:%d:%u]/[%s:%d:%u:%d:%u]\n",
- rm_encoding, map->rm_pt, (int) map->rm_rate, ptime, map_bit_rate,
+ rm_encoding, map->rm_pt, (int) map->rm_rate, codec_ms, map_bit_rate,
imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate);
if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
match = (map->rm_pt == imp->ianacode) ? 1 : 0;
@@ -6149,6 +6188,14 @@ void sofia_glue_parse_rtp_bugs(uint32_t *flag_pole, const char *str)
if (switch_stristr("~NEVER_SEND_MARKER", str)) {
*flag_pole &= ~RTP_BUG_NEVER_SEND_MARKER;
}
+
+ if (switch_stristr("IGNORE_DTMF_DURATION", str)) {
+ *flag_pole |= RTP_BUG_IGNORE_DTMF_DURATION;
+ }
+
+ if (switch_stristr("~IGNORE_DTMF_DURATION", str)) {
+ *flag_pole &= ~RTP_BUG_IGNORE_DTMF_DURATION;
+ }
}
char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_nat_parse_t *np)
diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c
index 0b7d0f33fa..288191807c 100644
--- a/src/mod/endpoints/mod_sofia/sofia_reg.c
+++ b/src/mod/endpoints/mod_sofia/sofia_reg.c
@@ -1078,7 +1078,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (exptime && v_event && *v_event) {
char *exp_var;
char *allow_multireg = NULL;
- int force_connectile = 0;
+ int auto_connectile = 0;
allow_multireg = switch_event_get_header(*v_event, "sip-allow-multiple-registrations");
if (allow_multireg && switch_false(allow_multireg)) {
@@ -1097,11 +1097,26 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (profile->rport_level == 3 && sip->sip_user_agent &&
sip->sip_user_agent->g_string && !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7)) {
- force_connectile = 1;
+ if (sip && sip->sip_via) {
+ const char *host = sip->sip_via->v_host;
+ const char *c_port = sip->sip_via->v_port;
+ int port = 0;
+
+ if (c_port) port = atoi(c_port);
+ if (!port) port = 5060;
+
+ if (host && strcmp(network_ip, host)) {
+ auto_connectile = 1;
+ } else if (port != network_port) {
+ auto_connectile = 1;
+ }
+ } else {
+ auto_connectile = 1;
+ }
}
- if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact")) || force_connectile) {
- if ((!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction-2.0")) || force_connectile) {
+ if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact")) || auto_connectile) {
+ if ((!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction-2.0")) || auto_connectile) {
char *path_encoded;
size_t path_encoded_len;
char my_contact_str[1024];
diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx
index f5e9e31f72..9ebd6ff9df 100644
--- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx
+++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx
@@ -1331,6 +1331,16 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_HOLD_MUSIC_VARIABLE_get() {
}
+SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get() {
+ char * jresult ;
+ char *result = 0 ;
+
+ result = (char *)("temp_hold_music");
+ jresult = SWIG_csharp_string_callback((const char *)result);
+ return jresult;
+}
+
+
SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_EXPORT_VARS_VARIABLE_get() {
char * jresult ;
char *result = 0 ;
@@ -7112,6 +7122,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_core_session_get_dmachine(void * jar
}
+SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_set_codec_slin(void * jarg1, void * jarg2) {
+ int jresult ;
+ switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
+ switch_slin_data_t *arg2 = (switch_slin_data_t *) 0 ;
+ switch_status_t result;
+
+ arg1 = (switch_core_session_t *)jarg1;
+ arg2 = (switch_slin_data_t *)jarg2;
+ result = (switch_status_t)switch_core_session_set_codec_slin(arg1,arg2);
+ jresult = result;
+ return jresult;
+}
+
+
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_core_get_uuid() {
char * jresult ;
char *result = 0 ;
@@ -10392,6 +10416,18 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_execute_sql_callback(void * ja
}
+SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_affected_rows(void * jarg1) {
+ int jresult ;
+ switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ;
+ int result;
+
+ arg1 = (switch_cache_db_handle_t *)jarg1;
+ result = (int)switch_cache_db_affected_rows(arg1);
+ jresult = result;
+ return jresult;
+}
+
+
SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_status(void * jarg1) {
switch_stream_handle_t *arg1 = (switch_stream_handle_t *) 0 ;
@@ -11972,6 +12008,30 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_is_digit_string(char * jarg1) {
}
+SWIGEXPORT char SWIGSTDCALL CSharp_switch_itodtmf(char jarg1) {
+ char jresult ;
+ char arg1 ;
+ char result;
+
+ arg1 = (char)jarg1;
+ result = (char)switch_itodtmf(arg1);
+ jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_switch_dtmftoi(char * jarg1) {
+ int jresult ;
+ char *arg1 = (char *) 0 ;
+ int result;
+
+ arg1 = (char *)jarg1;
+ result = (int)switch_dtmftoi(arg1);
+ jresult = result;
+ return jresult;
+}
+
+
SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_known_bitrate(unsigned char jarg1) {
unsigned long jresult ;
switch_payload_t arg1 ;
@@ -22102,6 +22162,119 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_api_interface(void * jarg1) {
}
+SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_session_set(void * jarg1, void * jarg2) {
+ switch_slin_data *arg1 = (switch_slin_data *) 0 ;
+ switch_core_session_t *arg2 = (switch_core_session_t *) 0 ;
+
+ arg1 = (switch_slin_data *)jarg1;
+ arg2 = (switch_core_session_t *)jarg2;
+ if (arg1) (arg1)->session = arg2;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_switch_slin_data_session_get(void * jarg1) {
+ void * jresult ;
+ switch_slin_data *arg1 = (switch_slin_data *) 0 ;
+ switch_core_session_t *result = 0 ;
+
+ arg1 = (switch_slin_data *)jarg1;
+ result = (switch_core_session_t *) ((arg1)->session);
+ jresult = (void *)result;
+ return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_write_frame_set(void * jarg1, void * jarg2) {
+ switch_slin_data *arg1 = (switch_slin_data *) 0 ;
+ switch_frame_t *arg2 = (switch_frame_t *) 0 ;
+
+ arg1 = (switch_slin_data *)jarg1;
+ arg2 = (switch_frame_t *)jarg2;
+ if (arg1) (arg1)->write_frame = *arg2;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_switch_slin_data_write_frame_get(void * jarg1) {
+ void * jresult ;
+ switch_slin_data *arg1 = (switch_slin_data *) 0 ;
+ switch_frame_t *result = 0 ;
+
+ arg1 = (switch_slin_data *)jarg1;
+ result = (switch_frame_t *)& ((arg1)->write_frame);
+ jresult = (void *)result;
+ return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_codec_set(void * jarg1, void * jarg2) {
+ switch_slin_data *arg1 = (switch_slin_data *) 0 ;
+ switch_codec_t *arg2 = (switch_codec_t *) 0 ;
+
+ arg1 = (switch_slin_data *)jarg1;
+ arg2 = (switch_codec_t *)jarg2;
+ if (arg1) (arg1)->codec = *arg2;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_switch_slin_data_codec_get(void * jarg1) {
+ void * jresult ;
+ switch_slin_data *arg1 = (switch_slin_data *) 0 ;
+ switch_codec_t *result = 0 ;
+
+ arg1 = (switch_slin_data *)jarg1;
+ result = (switch_codec_t *)& ((arg1)->codec);
+ jresult = (void *)result;
+ return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_frame_data_set(void * jarg1, char * jarg2) {
+ switch_slin_data *arg1 = (switch_slin_data *) 0 ;
+ char *arg2 ;
+
+ arg1 = (switch_slin_data *)jarg1;
+ arg2 = (char *)jarg2;
+ {
+ if(arg2) {
+ strncpy((char*)arg1->frame_data, (const char *)arg2, 4096-1);
+ arg1->frame_data[4096-1] = 0;
+ } else {
+ arg1->frame_data[0] = 0;
+ }
+ }
+}
+
+
+SWIGEXPORT char * SWIGSTDCALL CSharp_switch_slin_data_frame_data_get(void * jarg1) {
+ char * jresult ;
+ switch_slin_data *arg1 = (switch_slin_data *) 0 ;
+ char *result = 0 ;
+
+ arg1 = (switch_slin_data *)jarg1;
+ result = (char *)(char *) ((arg1)->frame_data);
+ jresult = SWIG_csharp_string_callback((const char *)result);
+ return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_slin_data() {
+ void * jresult ;
+ switch_slin_data *result = 0 ;
+
+ result = (switch_slin_data *)new switch_slin_data();
+ jresult = (void *)result;
+ return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_slin_data(void * jarg1) {
+ switch_slin_data *arg1 = (switch_slin_data *) 0 ;
+
+ arg1 = (switch_slin_data *)jarg1;
+ delete arg1;
+}
+
+
SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_timetable_profile_created_set(void * jarg1, void * jarg2) {
switch_channel_timetable *arg1 = (switch_channel_timetable *) 0 ;
switch_time_t arg2 ;
@@ -22834,6 +23007,30 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_variable_partner(void *
}
+SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music(void * jarg1) {
+ char * jresult ;
+ switch_channel_t *arg1 = (switch_channel_t *) 0 ;
+ char *result = 0 ;
+
+ arg1 = (switch_channel_t *)jarg1;
+ result = (char *)switch_channel_get_hold_music(arg1);
+ jresult = SWIG_csharp_string_callback((const char *)result);
+ return jresult;
+}
+
+
+SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music_partner(void * jarg1) {
+ char * jresult ;
+ switch_channel_t *arg1 = (switch_channel_t *) 0 ;
+ char *result = 0 ;
+
+ arg1 = (switch_channel_t *)jarg1;
+ result = (char *)switch_channel_get_hold_music_partner(arg1);
+ jresult = SWIG_csharp_string_callback((const char *)result);
+ return jresult;
+}
+
+
SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, char * jarg4, int jarg5) {
int jresult ;
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
@@ -23079,6 +23276,20 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_test_cap(void * jarg1
}
+SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_test_cap_partner(void * jarg1, int jarg2) {
+ unsigned long jresult ;
+ switch_channel_t *arg1 = (switch_channel_t *) 0 ;
+ switch_channel_cap_t arg2 ;
+ uint32_t result;
+
+ arg1 = (switch_channel_t *)jarg1;
+ arg2 = (switch_channel_cap_t)jarg2;
+ result = (uint32_t)switch_channel_test_cap_partner(arg1,arg2);
+ jresult = (unsigned long)result;
+ return jresult;
+}
+
+
SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_set_flag_partner(void * jarg1, int jarg2) {
int jresult ;
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
@@ -28362,6 +28573,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_deactivate_jitter_buffer(void * jar
}
+SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_pause_jitter_buffer(void * jarg1, int jarg2) {
+ int jresult ;
+ switch_rtp_t *arg1 = (switch_rtp_t *) 0 ;
+ switch_bool_t arg2 ;
+ switch_status_t result;
+
+ arg1 = (switch_rtp_t *)jarg1;
+ arg2 = (switch_bool_t)jarg2;
+ result = (switch_status_t)switch_rtp_pause_jitter_buffer(arg1,arg2);
+ jresult = result;
+ return jresult;
+}
+
+
SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_flag(void * jarg1, unsigned long jarg2) {
switch_rtp_t *arg1 = (switch_rtp_t *) 0 ;
switch_rtp_flag_t arg2 ;
@@ -33252,6 +33477,24 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_CoreSession_voice_name_get(void * jarg1) {
}
+SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_insertFile(void * jarg1, char * jarg2, char * jarg3, int jarg4) {
+ int jresult ;
+ CoreSession *arg1 = (CoreSession *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ int arg4 ;
+ int result;
+
+ arg1 = (CoreSession *)jarg1;
+ arg2 = (char *)jarg2;
+ arg3 = (char *)jarg3;
+ arg4 = (int)jarg4;
+ result = (int)(arg1)->insertFile((char const *)arg2,(char const *)arg3,arg4);
+ jresult = result;
+ return jresult;
+}
+
+
SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_Answer(void * jarg1) {
int jresult ;
CoreSession *arg1 = (CoreSession *) 0 ;
diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx
index d05f4f1213..aa2a84f3f6 100644
--- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx
+++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx
@@ -1422,6 +1422,17 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_HOLD_MUSIC_VARIABLE_get() {
}
+SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get() {
+ char * jresult ;
+ char *result = 0 ;
+
+ result = (char *) "temp_hold_music";
+
+ jresult = SWIG_csharp_string_callback((const char *)result);
+ return jresult;
+}
+
+
SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_EXPORT_VARS_VARIABLE_get() {
char * jresult ;
char *result = 0 ;
@@ -12304,6 +12315,30 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_is_digit_string(char * jarg1) {
}
+SWIGEXPORT char SWIGSTDCALL CSharp_switch_itodtmf(char jarg1) {
+ char jresult ;
+ char arg1 ;
+ char result;
+
+ arg1 = (char)jarg1;
+ result = (char)switch_itodtmf(arg1);
+ jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_switch_dtmftoi(char * jarg1) {
+ int jresult ;
+ char *arg1 = (char *) 0 ;
+ int result;
+
+ arg1 = (char *)jarg1;
+ result = (int)switch_dtmftoi(arg1);
+ jresult = result;
+ return jresult;
+}
+
+
SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_known_bitrate(unsigned char jarg1) {
unsigned long jresult ;
switch_payload_t arg1 ;
@@ -23501,6 +23536,30 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_variable_partner(void *
}
+SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music(void * jarg1) {
+ char * jresult ;
+ switch_channel_t *arg1 = (switch_channel_t *) 0 ;
+ char *result = 0 ;
+
+ arg1 = (switch_channel_t *)jarg1;
+ result = (char *)switch_channel_get_hold_music(arg1);
+ jresult = SWIG_csharp_string_callback((const char *)result);
+ return jresult;
+}
+
+
+SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music_partner(void * jarg1) {
+ char * jresult ;
+ switch_channel_t *arg1 = (switch_channel_t *) 0 ;
+ char *result = 0 ;
+
+ arg1 = (switch_channel_t *)jarg1;
+ result = (char *)switch_channel_get_hold_music_partner(arg1);
+ jresult = SWIG_csharp_string_callback((const char *)result);
+ return jresult;
+}
+
+
SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, char * jarg4, int jarg5) {
int jresult ;
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
@@ -23746,6 +23805,20 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_test_cap(void * jarg1
}
+SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_test_cap_partner(void * jarg1, int jarg2) {
+ unsigned long jresult ;
+ switch_channel_t *arg1 = (switch_channel_t *) 0 ;
+ switch_channel_cap_t arg2 ;
+ uint32_t result;
+
+ arg1 = (switch_channel_t *)jarg1;
+ arg2 = (switch_channel_cap_t)jarg2;
+ result = (uint32_t)switch_channel_test_cap_partner(arg1,arg2);
+ jresult = (unsigned long)result;
+ return jresult;
+}
+
+
SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_set_flag_partner(void * jarg1, int jarg2) {
int jresult ;
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
@@ -29077,6 +29150,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_deactivate_jitter_buffer(void * jar
}
+SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_pause_jitter_buffer(void * jarg1, int jarg2) {
+ int jresult ;
+ switch_rtp_t *arg1 = (switch_rtp_t *) 0 ;
+ switch_bool_t arg2 ;
+ switch_status_t result;
+
+ arg1 = (switch_rtp_t *)jarg1;
+ arg2 = (switch_bool_t)jarg2;
+ result = (switch_status_t)switch_rtp_pause_jitter_buffer(arg1,arg2);
+ jresult = result;
+ return jresult;
+}
+
+
SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_flag(void * jarg1, unsigned long jarg2) {
switch_rtp_t *arg1 = (switch_rtp_t *) 0 ;
switch_rtp_flag_t arg2 ;
diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs
index b792fb0ac8..059fb89a1c 100644
--- a/src/mod/languages/mod_managed/managed/swig.2010.cs
+++ b/src/mod/languages/mod_managed/managed/swig.2010.cs
@@ -224,6 +224,11 @@ public class CoreSession : IDisposable {
}
}
+ public int insertFile(string file, string insert_file, int sample_point) {
+ int ret = freeswitchPINVOKE.CoreSession_insertFile(swigCPtr, file, insert_file, sample_point);
+ return ret;
+ }
+
public int Answer() {
int ret = freeswitchPINVOKE.CoreSession_Answer(swigCPtr);
return ret;
@@ -1362,6 +1367,11 @@ public class freeswitch {
return ret;
}
+ public static switch_status_t switch_core_session_set_codec_slin(SWIGTYPE_p_switch_core_session session, switch_slin_data data) {
+ switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_set_codec_slin(SWIGTYPE_p_switch_core_session.getCPtr(session), switch_slin_data.getCPtr(data));
+ return ret;
+ }
+
public static string switch_core_get_uuid() {
string ret = freeswitchPINVOKE.switch_core_get_uuid();
return ret;
@@ -2338,6 +2348,11 @@ public class freeswitch {
return ret;
}
+ public static int switch_cache_db_affected_rows(switch_cache_db_handle_t dbh) {
+ int ret = freeswitchPINVOKE.switch_cache_db_affected_rows(switch_cache_db_handle_t.getCPtr(dbh));
+ return ret;
+ }
+
public static void switch_cache_db_status(switch_stream_handle stream) {
freeswitchPINVOKE.switch_cache_db_status(switch_stream_handle.getCPtr(stream));
}
@@ -2732,6 +2747,16 @@ public class freeswitch {
return ret;
}
+ public static char switch_itodtmf(char i) {
+ char ret = freeswitchPINVOKE.switch_itodtmf(i);
+ return ret;
+ }
+
+ public static int switch_dtmftoi(string s) {
+ int ret = freeswitchPINVOKE.switch_dtmftoi(s);
+ return ret;
+ }
+
public static uint switch_known_bitrate(byte payload) {
uint ret = freeswitchPINVOKE.switch_known_bitrate(payload);
return ret;
@@ -3281,6 +3306,16 @@ public class freeswitch {
return ret;
}
+ public static string switch_channel_get_hold_music(SWIGTYPE_p_switch_channel channel) {
+ string ret = freeswitchPINVOKE.switch_channel_get_hold_music(SWIGTYPE_p_switch_channel.getCPtr(channel));
+ return ret;
+ }
+
+ public static string switch_channel_get_hold_music_partner(SWIGTYPE_p_switch_channel channel) {
+ string ret = freeswitchPINVOKE.switch_channel_get_hold_music_partner(SWIGTYPE_p_switch_channel.getCPtr(channel));
+ return ret;
+ }
+
public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string val, string export_varname, switch_bool_t var_check) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, val, export_varname, (int)var_check);
return ret;
@@ -3369,6 +3404,11 @@ public class freeswitch {
return ret;
}
+ public static uint switch_channel_test_cap_partner(SWIGTYPE_p_switch_channel channel, switch_channel_cap_t cap) {
+ uint ret = freeswitchPINVOKE.switch_channel_test_cap_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)cap);
+ return ret;
+ }
+
public static switch_bool_t switch_channel_set_flag_partner(SWIGTYPE_p_switch_channel channel, switch_channel_flag_t flag) {
switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_channel_set_flag_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)flag);
return ret;
@@ -4664,6 +4704,11 @@ public class freeswitch {
return ret;
}
+ public static switch_status_t switch_rtp_pause_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, switch_bool_t pause) {
+ switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_pause_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), (int)pause);
+ return ret;
+ }
+
public static void switch_rtp_set_flag(SWIGTYPE_p_switch_rtp rtp_session, uint flags) {
freeswitchPINVOKE.switch_rtp_set_flag(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), flags);
}
@@ -5418,6 +5463,7 @@ public class freeswitch {
public static readonly string SWITCH_PROXY_MEDIA_VARIABLE = freeswitchPINVOKE.SWITCH_PROXY_MEDIA_VARIABLE_get();
public static readonly string SWITCH_ENDPOINT_DISPOSITION_VARIABLE = freeswitchPINVOKE.SWITCH_ENDPOINT_DISPOSITION_VARIABLE_get();
public static readonly string SWITCH_HOLD_MUSIC_VARIABLE = freeswitchPINVOKE.SWITCH_HOLD_MUSIC_VARIABLE_get();
+ public static readonly string SWITCH_TEMP_HOLD_MUSIC_VARIABLE = freeswitchPINVOKE.SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get();
public static readonly string SWITCH_EXPORT_VARS_VARIABLE = freeswitchPINVOKE.SWITCH_EXPORT_VARS_VARIABLE_get();
public static readonly string SWITCH_BRIDGE_EXPORT_VARS_VARIABLE = freeswitchPINVOKE.SWITCH_BRIDGE_EXPORT_VARS_VARIABLE_get();
public static readonly string SWITCH_R_SDP_VARIABLE = freeswitchPINVOKE.SWITCH_R_SDP_VARIABLE_get();
@@ -6010,6 +6056,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_SWITCH_HOLD_MUSIC_VARIABLE_get")]
public static extern string SWITCH_HOLD_MUSIC_VARIABLE_get();
+ [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get")]
+ public static extern string SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get();
+
[DllImport("mod_managed", EntryPoint="CSharp_SWITCH_EXPORT_VARS_VARIABLE_get")]
public static extern string SWITCH_EXPORT_VARS_VARIABLE_get();
@@ -7474,6 +7523,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_get_dmachine")]
public static extern IntPtr switch_core_session_get_dmachine(HandleRef jarg1);
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_set_codec_slin")]
+ public static extern int switch_core_session_set_codec_slin(HandleRef jarg1, HandleRef jarg2);
+
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_uuid")]
public static extern string switch_core_get_uuid();
@@ -8218,6 +8270,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_execute_sql_callback")]
public static extern int switch_cache_db_execute_sql_callback(HandleRef jarg1, string jarg2, HandleRef jarg3, HandleRef jarg4, ref string jarg5);
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_affected_rows")]
+ public static extern int switch_cache_db_affected_rows(HandleRef jarg1);
+
[DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_status")]
public static extern void switch_cache_db_status(HandleRef jarg1);
@@ -8590,6 +8645,12 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_is_digit_string")]
public static extern int switch_is_digit_string(string jarg1);
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_itodtmf")]
+ public static extern char switch_itodtmf(char jarg1);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_dtmftoi")]
+ public static extern int switch_dtmftoi(string jarg1);
+
[DllImport("mod_managed", EntryPoint="CSharp_switch_known_bitrate")]
public static extern uint switch_known_bitrate(byte jarg1);
@@ -11149,6 +11210,36 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_delete_switch_api_interface")]
public static extern void delete_switch_api_interface(HandleRef jarg1);
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_session_set")]
+ public static extern void switch_slin_data_session_set(HandleRef jarg1, HandleRef jarg2);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_session_get")]
+ public static extern IntPtr switch_slin_data_session_get(HandleRef jarg1);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_write_frame_set")]
+ public static extern void switch_slin_data_write_frame_set(HandleRef jarg1, HandleRef jarg2);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_write_frame_get")]
+ public static extern IntPtr switch_slin_data_write_frame_get(HandleRef jarg1);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_codec_set")]
+ public static extern void switch_slin_data_codec_set(HandleRef jarg1, HandleRef jarg2);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_codec_get")]
+ public static extern IntPtr switch_slin_data_codec_get(HandleRef jarg1);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_frame_data_set")]
+ public static extern void switch_slin_data_frame_data_set(HandleRef jarg1, string jarg2);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_frame_data_get")]
+ public static extern string switch_slin_data_frame_data_get(HandleRef jarg1);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_new_switch_slin_data")]
+ public static extern IntPtr new_switch_slin_data();
+
+ [DllImport("mod_managed", EntryPoint="CSharp_delete_switch_slin_data")]
+ public static extern void delete_switch_slin_data(HandleRef jarg1);
+
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_timetable_profile_created_set")]
public static extern void switch_channel_timetable_profile_created_set(HandleRef jarg1, HandleRef jarg2);
@@ -11311,6 +11402,12 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_variable_partner")]
public static extern string switch_channel_get_variable_partner(HandleRef jarg1, string jarg2);
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music")]
+ public static extern string switch_channel_get_hold_music(HandleRef jarg1);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music_partner")]
+ public static extern string switch_channel_get_hold_music_partner(HandleRef jarg1);
+
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_var_check")]
public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, string jarg4, int jarg5);
@@ -11368,6 +11465,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_test_cap")]
public static extern uint switch_channel_test_cap(HandleRef jarg1, int jarg2);
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_test_cap_partner")]
+ public static extern uint switch_channel_test_cap_partner(HandleRef jarg1, int jarg2);
+
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_flag_partner")]
public static extern int switch_channel_set_flag_partner(HandleRef jarg1, int jarg2);
@@ -12481,6 +12581,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_deactivate_jitter_buffer")]
public static extern int switch_rtp_deactivate_jitter_buffer(HandleRef jarg1);
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_pause_jitter_buffer")]
+ public static extern int switch_rtp_pause_jitter_buffer(HandleRef jarg1, int jarg2);
+
[DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_flag")]
public static extern void switch_rtp_set_flag(HandleRef jarg1, uint jarg2);
@@ -13672,6 +13775,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_CoreSession_voice_name_get")]
public static extern string CoreSession_voice_name_get(HandleRef jarg1);
+ [DllImport("mod_managed", EntryPoint="CSharp_CoreSession_insertFile")]
+ public static extern int CoreSession_insertFile(HandleRef jarg1, string jarg2, string jarg3, int jarg4);
+
[DllImport("mod_managed", EntryPoint="CSharp_CoreSession_Answer")]
public static extern int CoreSession_Answer(HandleRef jarg1);
@@ -21515,6 +21621,8 @@ public enum switch_channel_cap_t {
CC_MEDIA_ACK = 1,
CC_BYPASS_MEDIA,
CC_PROXY_MEDIA,
+ CC_JITTERBUFFER,
+ CC_FS_RTP,
CC_FLAG_MAX
}
@@ -29531,6 +29639,98 @@ public enum switch_signal_t {
namespace FreeSWITCH.Native {
+using System;
+using System.Runtime.InteropServices;
+
+public class switch_slin_data : IDisposable {
+ private HandleRef swigCPtr;
+ protected bool swigCMemOwn;
+
+ internal switch_slin_data(IntPtr cPtr, bool cMemoryOwn) {
+ swigCMemOwn = cMemoryOwn;
+ swigCPtr = new HandleRef(this, cPtr);
+ }
+
+ internal static HandleRef getCPtr(switch_slin_data obj) {
+ return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+ }
+
+ ~switch_slin_data() {
+ Dispose();
+ }
+
+ public virtual void Dispose() {
+ lock(this) {
+ if (swigCPtr.Handle != IntPtr.Zero) {
+ if (swigCMemOwn) {
+ swigCMemOwn = false;
+ freeswitchPINVOKE.delete_switch_slin_data(swigCPtr);
+ }
+ swigCPtr = new HandleRef(null, IntPtr.Zero);
+ }
+ GC.SuppressFinalize(this);
+ }
+ }
+
+ public SWIGTYPE_p_switch_core_session session {
+ set {
+ freeswitchPINVOKE.switch_slin_data_session_set(swigCPtr, SWIGTYPE_p_switch_core_session.getCPtr(value));
+ }
+ get {
+ IntPtr cPtr = freeswitchPINVOKE.switch_slin_data_session_get(swigCPtr);
+ SWIGTYPE_p_switch_core_session ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_core_session(cPtr, false);
+ return ret;
+ }
+ }
+
+ public switch_frame write_frame {
+ set {
+ freeswitchPINVOKE.switch_slin_data_write_frame_set(swigCPtr, switch_frame.getCPtr(value));
+ }
+ get {
+ IntPtr cPtr = freeswitchPINVOKE.switch_slin_data_write_frame_get(swigCPtr);
+ switch_frame ret = (cPtr == IntPtr.Zero) ? null : new switch_frame(cPtr, false);
+ return ret;
+ }
+ }
+
+ public switch_codec codec {
+ set {
+ freeswitchPINVOKE.switch_slin_data_codec_set(swigCPtr, switch_codec.getCPtr(value));
+ }
+ get {
+ IntPtr cPtr = freeswitchPINVOKE.switch_slin_data_codec_get(swigCPtr);
+ switch_codec ret = (cPtr == IntPtr.Zero) ? null : new switch_codec(cPtr, false);
+ return ret;
+ }
+ }
+
+ public string frame_data {
+ set {
+ freeswitchPINVOKE.switch_slin_data_frame_data_set(swigCPtr, value);
+ }
+ get {
+ string ret = freeswitchPINVOKE.switch_slin_data_frame_data_get(swigCPtr);
+ return ret;
+ }
+ }
+
+ public switch_slin_data() : this(freeswitchPINVOKE.new_switch_slin_data(), true) {
+ }
+
+}
+
+}
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.1
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace FreeSWITCH.Native {
+
[System.Flags] public enum switch_speech_flag_enum_t {
SWITCH_SPEECH_FLAG_NONE = 0,
SWITCH_SPEECH_FLAG_HASTEXT = (1 << 0),
diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs
index 849a6f62a4..5a2188ac83 100644
--- a/src/mod/languages/mod_managed/managed/swig.cs
+++ b/src/mod/languages/mod_managed/managed/swig.cs
@@ -2732,6 +2732,16 @@ public class freeswitch {
return ret;
}
+ public static char switch_itodtmf(char i) {
+ char ret = freeswitchPINVOKE.switch_itodtmf(i);
+ return ret;
+ }
+
+ public static int switch_dtmftoi(string s) {
+ int ret = freeswitchPINVOKE.switch_dtmftoi(s);
+ return ret;
+ }
+
public static uint switch_known_bitrate(byte payload) {
uint ret = freeswitchPINVOKE.switch_known_bitrate(payload);
return ret;
@@ -3281,6 +3291,16 @@ public class freeswitch {
return ret;
}
+ public static string switch_channel_get_hold_music(SWIGTYPE_p_switch_channel channel) {
+ string ret = freeswitchPINVOKE.switch_channel_get_hold_music(SWIGTYPE_p_switch_channel.getCPtr(channel));
+ return ret;
+ }
+
+ public static string switch_channel_get_hold_music_partner(SWIGTYPE_p_switch_channel channel) {
+ string ret = freeswitchPINVOKE.switch_channel_get_hold_music_partner(SWIGTYPE_p_switch_channel.getCPtr(channel));
+ return ret;
+ }
+
public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string val, string export_varname, switch_bool_t var_check) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, val, export_varname, (int)var_check);
return ret;
@@ -3369,6 +3389,11 @@ public class freeswitch {
return ret;
}
+ public static uint switch_channel_test_cap_partner(SWIGTYPE_p_switch_channel channel, switch_channel_cap_t cap) {
+ uint ret = freeswitchPINVOKE.switch_channel_test_cap_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)cap);
+ return ret;
+ }
+
public static switch_bool_t switch_channel_set_flag_partner(SWIGTYPE_p_switch_channel channel, switch_channel_flag_t flag) {
switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_channel_set_flag_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)flag);
return ret;
@@ -4664,6 +4689,11 @@ public class freeswitch {
return ret;
}
+ public static switch_status_t switch_rtp_pause_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, switch_bool_t pause) {
+ switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_pause_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), (int)pause);
+ return ret;
+ }
+
public static void switch_rtp_set_flag(SWIGTYPE_p_switch_rtp rtp_session, uint flags) {
freeswitchPINVOKE.switch_rtp_set_flag(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), flags);
}
@@ -5418,6 +5448,7 @@ public class freeswitch {
public static readonly string SWITCH_PROXY_MEDIA_VARIABLE = freeswitchPINVOKE.SWITCH_PROXY_MEDIA_VARIABLE_get();
public static readonly string SWITCH_ENDPOINT_DISPOSITION_VARIABLE = freeswitchPINVOKE.SWITCH_ENDPOINT_DISPOSITION_VARIABLE_get();
public static readonly string SWITCH_HOLD_MUSIC_VARIABLE = freeswitchPINVOKE.SWITCH_HOLD_MUSIC_VARIABLE_get();
+ public static readonly string SWITCH_TEMP_HOLD_MUSIC_VARIABLE = freeswitchPINVOKE.SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get();
public static readonly string SWITCH_EXPORT_VARS_VARIABLE = freeswitchPINVOKE.SWITCH_EXPORT_VARS_VARIABLE_get();
public static readonly string SWITCH_BRIDGE_EXPORT_VARS_VARIABLE = freeswitchPINVOKE.SWITCH_BRIDGE_EXPORT_VARS_VARIABLE_get();
public static readonly string SWITCH_R_SDP_VARIABLE = freeswitchPINVOKE.SWITCH_R_SDP_VARIABLE_get();
@@ -6006,6 +6037,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_SWITCH_HOLD_MUSIC_VARIABLE_get")]
public static extern string SWITCH_HOLD_MUSIC_VARIABLE_get();
+ [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get")]
+ public static extern string SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get();
+
[DllImport("mod_managed", EntryPoint="CSharp_SWITCH_EXPORT_VARS_VARIABLE_get")]
public static extern string SWITCH_EXPORT_VARS_VARIABLE_get();
@@ -8589,6 +8623,12 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_is_digit_string")]
public static extern int switch_is_digit_string(string jarg1);
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_itodtmf")]
+ public static extern char switch_itodtmf(char jarg1);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_dtmftoi")]
+ public static extern int switch_dtmftoi(string jarg1);
+
[DllImport("mod_managed", EntryPoint="CSharp_switch_known_bitrate")]
public static extern uint switch_known_bitrate(byte jarg1);
@@ -11310,6 +11350,12 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_variable_partner")]
public static extern string switch_channel_get_variable_partner(HandleRef jarg1, string jarg2);
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music")]
+ public static extern string switch_channel_get_hold_music(HandleRef jarg1);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music_partner")]
+ public static extern string switch_channel_get_hold_music_partner(HandleRef jarg1);
+
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_var_check")]
public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, string jarg4, int jarg5);
@@ -11367,6 +11413,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_test_cap")]
public static extern uint switch_channel_test_cap(HandleRef jarg1, int jarg2);
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_test_cap_partner")]
+ public static extern uint switch_channel_test_cap_partner(HandleRef jarg1, int jarg2);
+
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_flag_partner")]
public static extern int switch_channel_set_flag_partner(HandleRef jarg1, int jarg2);
@@ -12480,6 +12529,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_deactivate_jitter_buffer")]
public static extern int switch_rtp_deactivate_jitter_buffer(HandleRef jarg1);
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_pause_jitter_buffer")]
+ public static extern int switch_rtp_pause_jitter_buffer(HandleRef jarg1, int jarg2);
+
[DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_flag")]
public static extern void switch_rtp_set_flag(HandleRef jarg1, uint jarg2);
@@ -21477,6 +21529,8 @@ public enum switch_channel_cap_t {
CC_MEDIA_ACK = 1,
CC_BYPASS_MEDIA,
CC_PROXY_MEDIA,
+ CC_JITTERBUFFER,
+ CC_FS_RTP,
CC_FLAG_MAX
}
diff --git a/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c b/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
index be06b148cd..468190d887 100644
--- a/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
+++ b/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
@@ -744,6 +744,7 @@ abyss_bool handler_hook(TSession * r)
if (dateValue) {
ResponseAddField(r, "Date", dateValue);
+ free(dateValue);
}
}
diff --git a/src/switch_core_session.c b/src/switch_core_session.c
index 9319abc535..4836aae73f 100644
--- a/src/switch_core_session.c
+++ b/src/switch_core_session.c
@@ -58,6 +58,39 @@ SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *sess
session->soft_lock = 0;
}
+SWITCH_DECLARE(switch_status_t) switch_core_session_set_codec_slin(switch_core_session_t *session, switch_slin_data_t *data)
+
+{
+ switch_codec_implementation_t read_impl = { 0 };
+ int interval;
+
+ switch_core_session_get_read_impl(session, &read_impl);
+ interval = read_impl.microseconds_per_packet / 1000;
+ data->session = session;
+
+ if (switch_core_codec_init(&data->codec,
+ "L16",
+ NULL,
+ read_impl.actual_samples_per_second,
+ interval,
+ 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) == SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
+ SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %dms\n", read_impl.actual_samples_per_second, interval);
+
+ memset(&data->write_frame, 0, sizeof(data->write_frame));
+
+ data->write_frame.codec = &data->codec;
+ data->write_frame.data = data->frame_data;
+ data->write_frame.buflen = sizeof(data->frame_data);
+ data->write_frame.datalen = 0;
+ switch_core_session_set_read_codec(session, &data->codec);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ return SWITCH_STATUS_FALSE;
+}
+
+
#ifdef SWITCH_DEBUG_RWLOCKS
SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_locate(const char *uuid_str, const char *file, const char *func, int line)
#else
diff --git a/src/switch_odbc.c b/src/switch_odbc.c
index 48ba62ce03..a7c2153304 100644
--- a/src/switch_odbc.c
+++ b/src/switch_odbc.c
@@ -57,6 +57,7 @@ struct switch_odbc_handle {
char odbc_driver[256];
BOOL is_firebird;
int affected_rows;
+ int num_retries;
};
#endif
@@ -90,6 +91,7 @@ SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, c
new_handle->env = SQL_NULL_HANDLE;
new_handle->state = SWITCH_ODBC_STATE_INIT;
new_handle->affected_rows = 0;
+ new_handle->num_retries = DEFAULT_ODBC_RETRIES;
return new_handle;
@@ -104,6 +106,15 @@ SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, c
return NULL;
}
+SWITCH_DECLARE(void) switch_odbc_set_num_retries(switch_odbc_handle_t *handle, int num_retries)
+{
+#ifdef SWITCH_HAVE_ODBC
+ if (handle) {
+ handle->num_retries = num_retries;
+ }
+#endif
+}
+
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_handle_t *handle)
{
#ifdef SWITCH_HAVE_ODBC
@@ -133,6 +144,53 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_h
#ifdef SWITCH_HAVE_ODBC
+static switch_odbc_status_t init_odbc_handles(switch_odbc_handle_t *handle, switch_bool_t do_reinit)
+{
+ int result;
+
+ if (!handle) {
+ return SWITCH_ODBC_FAIL;
+ }
+
+ /* if handle is already initialized, and we're supposed to reinit - free old handle first */
+ if (do_reinit == SWITCH_TRUE && handle->env != SQL_NULL_HANDLE) {
+ SQLFreeHandle(SQL_HANDLE_DBC, handle->con);
+ SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+ handle->env = SQL_NULL_HANDLE;
+ }
+
+ if (handle->env == SQL_NULL_HANDLE) {
+ result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env);
+
+ if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHandle\n");
+ handle->env = SQL_NULL_HANDLE; /* Reset handle value, just in case */
+ return SWITCH_ODBC_FAIL;
+ }
+
+ result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
+
+ if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SetEnv\n");
+ SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+ handle->env = SQL_NULL_HANDLE; /* Reset handle value after it's freed */
+ return SWITCH_ODBC_FAIL;
+ }
+
+ result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con);
+
+ if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHDB %d\n", result);
+ SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+ handle->env = SQL_NULL_HANDLE; /* Reset handle value after it's freed */
+ return SWITCH_ODBC_FAIL;
+ }
+ SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
+ }
+
+ return SWITCH_ODBC_SUCCESS;
+}
+
static int db_is_up(switch_odbc_handle_t *handle)
{
int ret = 0;
@@ -143,12 +201,18 @@ static int db_is_up(switch_odbc_handle_t *handle)
switch_odbc_status_t recon = 0;
char *err_str = NULL;
SQLCHAR sql[255] = "";
- int max_tries = 120;
+ int max_tries = DEFAULT_ODBC_RETRIES;
int code = 0;
SQLRETURN rc;
SQLSMALLINT nresultcols;
+ if (handle) {
+ max_tries = handle->num_retries;
+ if (max_tries < 1)
+ max_tries = DEFAULT_ODBC_RETRIES;
+ }
+
top:
if (!handle) {
@@ -199,6 +263,13 @@ static int db_is_up(switch_odbc_handle_t *handle)
error:
err_str = switch_odbc_handle_get_error(handle, stmt);
+
+ /* Make sure to free the handle before we try to reconnect */
+ if (stmt) {
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ stmt = NULL;
+ }
+
recon = switch_odbc_handle_connect(handle);
max_tries--;
@@ -228,11 +299,6 @@ static int db_is_up(switch_odbc_handle_t *handle)
goto done;
}
- if (stmt) {
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
- stmt = NULL;
- }
-
switch_safe_free(err_str);
switch_yield(1000000);
goto top;
@@ -274,31 +340,8 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_hand
SQLSMALLINT valueLength = 0;
int i = 0;
- if (handle->env == SQL_NULL_HANDLE) {
- result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env);
+ init_odbc_handles(handle, SWITCH_FALSE); /* Init ODBC handles, if they are already initialized, don't do it again */
- if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHandle\n");
- return SWITCH_ODBC_FAIL;
- }
-
- result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
-
- if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SetEnv\n");
- SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
- return SWITCH_ODBC_FAIL;
- }
-
- result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con);
-
- if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHDB %d\n", result);
- SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
- return SWITCH_ODBC_FAIL;
- }
- SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
- }
if (handle->state == SWITCH_ODBC_STATE_CONNECTED) {
switch_odbc_handle_disconnect(handle);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Re-connecting %s\n", handle->dsn);
@@ -325,7 +368,9 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_hand
SQLGetDiagRec(SQL_HANDLE_DBC, handle->con, 1, stat, &err, msg, 100, &mlen);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SQLConnect=%d errno=%d %s\n", result, (int) err, msg);
}
- SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+
+ /* Deallocate handles again, more chanses to succeed when reconnecting */
+ init_odbc_handles(handle, SWITCH_TRUE); /* Reinit ODBC handles */
return SWITCH_ODBC_FAIL;
}
@@ -554,6 +599,7 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_callback_exec_detailed(c
}
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ stmt = NULL; /* Make sure we don't try to free this handle again */
if (!err_cnt) {
return SWITCH_ODBC_SUCCESS;
@@ -593,8 +639,10 @@ SWITCH_DECLARE(void) switch_odbc_handle_destroy(switch_odbc_handle_t **handlep)
if (handle) {
switch_odbc_handle_disconnect(handle);
- SQLFreeHandle(SQL_HANDLE_DBC, handle->con);
- SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+ if (handle->env != SQL_NULL_HANDLE) {
+ SQLFreeHandle(SQL_HANDLE_DBC, handle->con);
+ SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+ }
switch_safe_free(handle->dsn);
switch_safe_free(handle->username);
switch_safe_free(handle->password);
diff --git a/src/switch_rtp.c b/src/switch_rtp.c
index 41d5fc98dd..038e1d981b 100644
--- a/src/switch_rtp.c
+++ b/src/switch_rtp.c
@@ -126,6 +126,7 @@ struct switch_rtp_rfc2833_data {
uint16_t in_digit_seq;
uint32_t in_digit_ts;
uint32_t in_digit_sanity;
+ uint32_t in_interleaved;
uint32_t timestamp_dtmf;
uint16_t last_duration;
uint32_t flip;
@@ -133,6 +134,7 @@ struct switch_rtp_rfc2833_data {
char last_digit;
switch_queue_t *dtmf_inqueue;
switch_mutex_t *dtmf_mutex;
+ uint8_t in_digit_queued;
};
struct switch_rtp {
@@ -2479,7 +2481,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
}
- if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) && (rtp_session->dtmf_data.out_digit_dur == 0 || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO))) {
+ if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) &&
+ (rtp_session->dtmf_data.out_digit_dur == 0 || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO))) {
return_cng_frame();
}
}
@@ -2819,7 +2822,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
#ifdef DEBUG_2833
if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) {
- printf("sanity %d\n", rtp_session->dtmf_data.in_digit_sanity);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sanity %d\n", rtp_session->dtmf_data.in_digit_sanity);
}
#endif
@@ -2869,7 +2872,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
}
#ifdef DEBUG_2833
- printf("packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned)
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned)
packet[1], (unsigned) packet[2], (unsigned) packet[3]);
#endif
@@ -2878,16 +2881,28 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
rtp_session->dtmf_data.in_digit_seq = in_digit_seq;
#ifdef DEBUG_2833
- printf("read: %c %u %u %u %u %d %d %s\n",
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read: %c %u %u %u %u %d %d %s\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq,
ts, duration, rtp_session->recv_msg.header.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : "");
#endif
+
+ if (!rtp_session->dtmf_data.in_digit_queued && (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) &&
+ rtp_session->dtmf_data.in_digit_ts) {
+ switch_dtmf_t dtmf = { key, switch_core_min_dtmf_duration(0) };
+#ifdef DEBUG_2833
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Early Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8);
+#endif
+ switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
+ rtp_session->dtmf_data.in_digit_queued = 1;
+ }
+
/* only set sanity if we do NOT ignore the packet */
if (rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.in_digit_sanity = 2000;
}
- if (rtp_session->dtmf_data.last_duration > duration && rtp_session->dtmf_data.last_duration > 0xFC17 && ts == rtp_session->dtmf_data.in_digit_ts) {
+ if (rtp_session->dtmf_data.last_duration > duration &&
+ rtp_session->dtmf_data.last_duration > 0xFC17 && ts == rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.flip++;
}
@@ -2902,18 +2917,26 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
dtmf.duration += rtp_session->dtmf_data.flip * 0xFFFF;
rtp_session->dtmf_data.flip = 0;
#ifdef DEBUG_2833
- printf("you're welcome!\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "you're welcome!\n");
#endif
}
#ifdef DEBUG_2833
- printf("done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n",
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n",
dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration);
#endif
- switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
+
+ if (!(rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) && !rtp_session->dtmf_data.in_digit_queued) {
+#ifdef DEBUG_2833
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8);
+#endif
+ switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
+ }
+
rtp_session->dtmf_data.last_digit = rtp_session->dtmf_data.first_digit;
rtp_session->dtmf_data.in_digit_ts = 0;
rtp_session->dtmf_data.in_digit_sanity = 0;
+ rtp_session->dtmf_data.in_digit_queued = 0;
do_cng = 1;
} else {
if (!switch_rtp_ready(rtp_session)) {
@@ -2932,7 +2955,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
rtp_session->dtmf_data.last_duration = duration;
} else {
#ifdef DEBUG_2833
- printf("drop: %c %u %u %u %u %d %d\n",
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "drop: %c %u %u %u %u %d %d\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end);
#endif
switch_cond_next();
@@ -2941,10 +2964,27 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
if (rtp_session->dtmf_data.in_digit_ts) {
+
+ }
+
+
+ if (bytes && rtp_session->dtmf_data.in_digit_ts) {
if (!switch_rtp_ready(rtp_session)) {
goto end;
}
- return_cng_frame();
+
+ if (!rtp_session->dtmf_data.in_interleaved && rtp_session->recv_msg.header.pt != rtp_session->recv_te) {
+ /* Drat, they are sending audio still as well as DTMF ok fine..... *sigh* */
+ rtp_session->dtmf_data.in_interleaved = 1;
+ }
+
+ if (rtp_session->dtmf_data.in_interleaved || (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION)) {
+ if (rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
+ goto recvfrom;
+ }
+ } else {
+ return_cng_frame();
+ }
}
timer_check:
@@ -3254,7 +3294,6 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp
}
frame->datalen = bytes;
-
return SWITCH_STATUS_SUCCESS;
}
@@ -3540,7 +3579,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
#ifdef RTP_DEBUG_WRITE_DELTA
{
int delta = (int) (now - rtp_session->send_time) / 1000;
- printf("WRITE %d delta %d\n", (int) bytes, delta);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WRITE %d delta %d\n", (int) bytes, delta);
}
#endif
rtp_session->send_time = now;