Add T31 modem support to mod_spandsp - similar to iaxmodem only wired into FS. Also merge configs into single spandsp.conf.xml --see in tree example--
This commit is contained in:
parent
0ed06ad710
commit
d91f67d0e3
|
@ -1,4 +1,39 @@
|
|||
<configuration name="spandsp.conf" description="Tone detector descriptors">
|
||||
<configuration name="spandsp.conf" description="SpanDSP config">
|
||||
<modem-settings>
|
||||
<!--
|
||||
total-modems set to N will create that many soft-modems.
|
||||
If you use them with Hylafax you need the following for each one numbered 0..N:
|
||||
|
||||
1) A line like this in /etc/inittab:
|
||||
|
||||
f0:2345:respawn:/usr/lib/fax/faxgetty /dev/FS0
|
||||
|
||||
2) copy conf/config.FS0 to /var/spool/hylafax/etc (or wherver the appropriate dir is on your system)
|
||||
|
||||
Subsequent modem configs would incrment the 0 to 1 and so on.
|
||||
|
||||
-->
|
||||
<param name="total-modems" value="1"/>
|
||||
|
||||
<!-- Default context and dialplan to use on inbound calls from the modems -->
|
||||
<param name="context" value="default"/>
|
||||
<param name="dialplan" value="XML"/>
|
||||
|
||||
<!-- Extra tracing for debugging -->
|
||||
<param name="verbose" value="false"/>
|
||||
</modem-settings>
|
||||
|
||||
<fax-settings>
|
||||
<param name="use-ecm" value="true"/>
|
||||
<param name="verbose" value="false"/>
|
||||
<param name="disable-v17" value="false"/>
|
||||
<param name="ident" value="SpanDSP Fax Ident"/>
|
||||
<param name="header" value="SpanDSP Fax Header"/>
|
||||
|
||||
<param name="spool-dir" value="/tmp"/>
|
||||
<param name="file-prefix" value="faxrx"/>
|
||||
</fax-settings>
|
||||
|
||||
<descriptors>
|
||||
|
||||
<!-- These tones are defined in Annex to ITU Operational Bulletin No. 781 - 1.II.2003 -->
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
CountryCode: 1
|
||||
AreaCode: 800
|
||||
FAXNumber: +1.800.555.1212
|
||||
LongDistancePrefix: 1
|
||||
InternationalPrefix: 011
|
||||
DialStringRules: etc/dialrules
|
||||
ServerTracing: 0xFFF
|
||||
SessionTracing: 0xFFF
|
||||
RecvFileMode: 0600
|
||||
LogFileMode: 0600
|
||||
DeviceMode: 0600
|
||||
RingsBeforeAnswer: 1
|
||||
SpeakerVolume: off
|
||||
GettyArgs: "-h %l dx_%s"
|
||||
LocalIdentifier: "FS"
|
||||
TagLineFont: etc/lutRS18.pcf
|
||||
TagLineFormat: "From %%l|%c|Page %%P of %%T"
|
||||
MaxRecvPages: 200
|
||||
#
|
||||
#
|
||||
# Modem-related stuff: should reflect modem command interface
|
||||
# and hardware connection/cabling (e.g. flow control).
|
||||
#
|
||||
ModemType: Class1 # use this to supply a hint
|
||||
|
||||
#
|
||||
# Enabling this will use the hfaxd-protocol to set Caller*ID
|
||||
#
|
||||
#ModemSetOriginCmd: AT+VSID="%s","%d"
|
||||
|
||||
#
|
||||
# If "glare" during initialization becomes a problem then take
|
||||
# the modem off-hook during initialization, and then place it
|
||||
# back on-hook when done.
|
||||
#
|
||||
#ModemResetCmds: "ATH1\nAT+VCID=1" # enables CallID display
|
||||
#ModemReadyCmds: ATH0
|
||||
|
||||
Class1AdaptRecvCmd: AT+FAR=1
|
||||
Class1TMConnectDelay: 400 # counteract quick CONNECT response
|
||||
|
||||
#
|
||||
# If you have trouble with V.17 receiving or sending,
|
||||
# you may want to enable one of these, respectively.
|
||||
#
|
||||
#Class1RMQueryCmd: "!24,48,72,96" # enable this to disable V.17 receiving
|
||||
#Class1TMQueryCmd: "!24,48,72,96" # enable this to disable V.17 sending
|
||||
|
||||
#
|
||||
# You'll likely want Caller*ID display (also displays DID) enabled.
|
||||
#
|
||||
ModemResetCmds: AT+VCID=1 # enables CallID display
|
||||
|
||||
#
|
||||
# The pty does not support changing parity.
|
||||
#
|
||||
PagerTTYParity: none
|
||||
|
||||
#
|
||||
# If you are "missing" Caller*ID data on some calls (but not all)
|
||||
# and if you do not have adequate glare protection you may want to
|
||||
# not answer based on RINGs, but rather enable the CallIDAnswerLength
|
||||
# for NDID, disable AT+VCID=1 and do this:
|
||||
#
|
||||
#RingsBeforeAnswer: 0
|
||||
#ModemRingResponse: AT+VRID=1
|
||||
|
||||
# Uncomment DATE and TIME if you really want them, but you probably don't.
|
||||
#CallIDPattern: "DATE="
|
||||
#CallIDPattern: "TIME="
|
||||
CallIDPattern: "NMBR="
|
||||
CallIDPattern: "NAME="
|
||||
CallIDPattern: "ANID="
|
||||
#CallIDPattern: "USER=" # username provided by call
|
||||
#CallIDPattern: "PASS=" # password provided by call
|
||||
#CallIDPattern: "CDID=" # DID context in call
|
||||
CallIDPattern: "NDID="
|
||||
#CallIDAnswerLength: 4
|
|
@ -483,7 +483,7 @@ AC_PROG_GCC_TRADITIONAL
|
|||
AC_FUNC_MALLOC
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_STRFTIME
|
||||
AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs timerfd_create getdtablesize])
|
||||
AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs timerfd_create getdtablesize posix_openpt])
|
||||
AC_CHECK_FUNCS([sched_setscheduler setpriority setrlimit setgroups initgroups])
|
||||
AC_CHECK_FUNCS([wcsncmp setgroups asprintf setenv pselect gettimeofday localtime_r gmtime_r strcasecmp stricmp _stricmp])
|
||||
|
||||
|
@ -494,6 +494,9 @@ AC_CHECK_LIB(rt, clock_getres, [AC_DEFINE(HAVE_CLOCK_GETRES, 1, [Define if you h
|
|||
AC_CHECK_LIB(rt, clock_nanosleep, [AC_DEFINE(HAVE_CLOCK_NANOSLEEP, 1, [Define if you have clock_nanosleep()])])
|
||||
AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket))
|
||||
|
||||
AC_CHECK_FILE(/dev/ptmx, [AC_DEFINE(HAVE_DEV_PTMX, 1, [Define if you have /dev/ptmx])])
|
||||
AC_CHECK_LIB(util, openpty, [AC_DEFINE(HAVE_OPENPTY, 1, [Define if you have openpty()])])
|
||||
|
||||
AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[
|
||||
#include <sys/types.h>
|
||||
#include <time.h>])
|
||||
|
|
|
@ -4,15 +4,15 @@ MODNAME=mod_spandsp
|
|||
TIFF_DIR=$(switch_srcdir)/libs/tiff-3.8.2
|
||||
TIFF_BUILDDIR=$(switch_builddir)/libs/tiff-3.8.2
|
||||
TIFF_LA=$(TIFF_BUILDDIR)/libtiff/libtiff.la
|
||||
|
||||
BUILD_CFLAGS=
|
||||
SPANDSP_DIR=$(switch_srcdir)/libs/spandsp
|
||||
SPANDSP_BUILDDIR=$(switch_builddir)/libs/spandsp
|
||||
SPANDSP_LA=$(SPANDSP_BUILDDIR)/src/libspandsp.la
|
||||
|
||||
mod_LTLIBRARIES = mod_spandsp.la
|
||||
mod_spandsp_la_SOURCES = mod_spandsp.c udptl.c mod_spandsp_fax.c mod_spandsp_dsp.c mod_spandsp_codecs.c
|
||||
mod_spandsp_la_CFLAGS = $(AM_CFLAGS) -I$(SPANDSP_DIR)/src -I$(TIFF_DIR)/libtiff -I$(SPANDSP_BUILDDIR)/src -I$(TIFF_BUILDDIR)/libtiff -I.
|
||||
mod_spandsp_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(SPANDSP_LA) $(TIFF_LA) -ljpeg -lz
|
||||
mod_spandsp_la_SOURCES = mod_spandsp.c udptl.c mod_spandsp_fax.c mod_spandsp_dsp.c mod_spandsp_codecs.c mod_spandsp_modem.c
|
||||
mod_spandsp_la_CFLAGS = $(BUILD_CFLAGS) $(AM_CFLAGS) -I$(SPANDSP_DIR)/src -I$(TIFF_DIR)/libtiff -I$(SPANDSP_BUILDDIR)/src -I$(TIFF_BUILDDIR)/libtiff -I.
|
||||
mod_spandsp_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(SPANDSP_LA) $(TIFF_LA) -ljpeg -lz -lutil
|
||||
mod_spandsp_la_LDFLAGS = -avoid-version -module -no-undefined -shared
|
||||
|
||||
$(SPANDSP_LA): $(TIFF_LA) $(SPANDSP_DIR) $(SPANDSP_DIR)/.update
|
||||
|
|
|
@ -36,11 +36,14 @@
|
|||
|
||||
#include "mod_spandsp.h"
|
||||
#include <spandsp/version.h>
|
||||
#include "mod_spandsp_modem.h"
|
||||
|
||||
/* **************************************************************************
|
||||
FREESWITCH MODULE DEFINITIONS
|
||||
************************************************************************* */
|
||||
|
||||
struct spandsp_globals spandsp_globals = { 0 };
|
||||
|
||||
#define SPANFAX_RX_USAGE "<filename>"
|
||||
#define SPANFAX_TX_USAGE "<filename>"
|
||||
|
||||
|
@ -116,10 +119,9 @@ SWITCH_STANDARD_APP(spandsp_stop_fax_detect_session_function)
|
|||
|
||||
static void event_handler(switch_event_t *event)
|
||||
{
|
||||
mod_spandsp_fax_event_handler(event);
|
||||
load_configuration(1);
|
||||
}
|
||||
|
||||
|
||||
SWITCH_STANDARD_APP(t38_gateway_function)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
|
@ -261,12 +263,239 @@ SWITCH_STANDARD_API(stop_tone_detect_api)
|
|||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* **************************************************************************
|
||||
CONFIGURATION
|
||||
************************************************************************* */
|
||||
|
||||
switch_status_t load_configuration(switch_bool_t reload)
|
||||
{
|
||||
switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL, callprogress = NULL, xdescriptor = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
switch_mutex_lock(spandsp_globals.mutex);
|
||||
|
||||
if (spandsp_globals.tones) {
|
||||
switch_core_hash_destroy(&spandsp_globals.tones);
|
||||
}
|
||||
|
||||
if (spandsp_globals.config_pool) {
|
||||
switch_core_destroy_memory_pool(&spandsp_globals.config_pool);
|
||||
}
|
||||
|
||||
switch_core_new_memory_pool(&spandsp_globals.config_pool);
|
||||
switch_core_hash_init(&spandsp_globals.tones, spandsp_globals.config_pool);
|
||||
|
||||
spandsp_globals.modem_dialplan = "XML";
|
||||
spandsp_globals.modem_context = "default";
|
||||
spandsp_globals.modem_count = 1;
|
||||
|
||||
|
||||
spandsp_globals.enable_t38 = 1;
|
||||
spandsp_globals.total_sessions = 0;
|
||||
spandsp_globals.verbose = 0;
|
||||
spandsp_globals.use_ecm = 1;
|
||||
spandsp_globals.disable_v17 = 0;
|
||||
spandsp_globals.prepend_string = switch_core_strdup(spandsp_globals.config_pool, "fax");
|
||||
spandsp_globals.spool = switch_core_strdup(spandsp_globals.config_pool, "/tmp");
|
||||
spandsp_globals.ident = "SpanDSP Fax Ident";
|
||||
spandsp_globals.header = "SpanDSP Fax Header";
|
||||
|
||||
/* TODO make configuration param */
|
||||
spandsp_globals.tonedebug = 1;
|
||||
|
||||
if ((xml = switch_xml_open_cfg("spandsp.conf", &cfg, NULL)) || (xml = switch_xml_open_cfg("fax.conf", &cfg, NULL))) {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
if ((x_lists = switch_xml_child(cfg, "modem-settings"))) {
|
||||
for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {
|
||||
const char *name = switch_xml_attr(x_list, "name");
|
||||
const char *value = switch_xml_attr(x_list, "value");
|
||||
|
||||
if (zstr(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (zstr(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!reload && !strcmp(name, "total-modems")) {
|
||||
int tmp = atoi(value);
|
||||
|
||||
if (tmp > 0 && tmp < MAX_MODEMS) {
|
||||
spandsp_globals.modem_count = tmp;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%d] for total-modems\n", tmp);
|
||||
}
|
||||
} else if (!strcmp(name, "dialplan")) {
|
||||
spandsp_globals.modem_dialplan = switch_core_strdup(spandsp_globals.config_pool, value);
|
||||
} else if (!strcmp(name, "context")) {
|
||||
spandsp_globals.modem_context = switch_core_strdup(spandsp_globals.config_pool, value);
|
||||
} else if (!strcmp(name, "verbose")) {
|
||||
if (switch_true(value)) {
|
||||
spandsp_globals.modem_verbose = 1;
|
||||
} else {
|
||||
spandsp_globals.modem_verbose = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((x_lists = switch_xml_child(cfg, "fax-settings")) || (x_lists = switch_xml_child(cfg, "settings"))) {
|
||||
for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {
|
||||
const char *name = switch_xml_attr(x_list, "name");
|
||||
const char *value = switch_xml_attr(x_list, "value");
|
||||
|
||||
if (zstr(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (zstr(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(name, "use-ecm")) {
|
||||
if (switch_true(value))
|
||||
spandsp_globals.use_ecm = 1;
|
||||
else
|
||||
spandsp_globals.use_ecm = 0;
|
||||
} else if (!strcmp(name, "verbose")) {
|
||||
if (switch_true(value))
|
||||
spandsp_globals.verbose = 1;
|
||||
else
|
||||
spandsp_globals.verbose = 0;
|
||||
} else if (!strcmp(name, "disable-v17")) {
|
||||
if (switch_true(value))
|
||||
spandsp_globals.disable_v17 = 1;
|
||||
else
|
||||
spandsp_globals.disable_v17 = 0;
|
||||
} else if (!strcmp(name, "enable-t38")) {
|
||||
if (switch_true(value)) {
|
||||
spandsp_globals.enable_t38= 1;
|
||||
} else {
|
||||
spandsp_globals.enable_t38 = 0;
|
||||
}
|
||||
} else if (!strcmp(name, "enable-t38-request")) {
|
||||
if (switch_true(value)) {
|
||||
spandsp_globals.enable_t38_request = 1;
|
||||
} else {
|
||||
spandsp_globals.enable_t38_request = 0;
|
||||
}
|
||||
} else if (!strcmp(name, "ident")) {
|
||||
spandsp_globals.ident = switch_core_strdup(spandsp_globals.config_pool, value);
|
||||
} else if (!strcmp(name, "header")) {
|
||||
spandsp_globals.header = switch_core_strdup(spandsp_globals.config_pool, value);
|
||||
} else if (!strcmp(name, "spool-dir")) {
|
||||
spandsp_globals.spool = switch_core_strdup(spandsp_globals.config_pool, value);
|
||||
} else if (!strcmp(name, "file-prefix")) {
|
||||
spandsp_globals.prepend_string = switch_core_strdup(spandsp_globals.config_pool, value);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown parameter %s\n", name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure call progress detector */
|
||||
if ((callprogress = switch_xml_child(cfg, "descriptors"))) {
|
||||
for (xdescriptor = switch_xml_child(callprogress, "descriptor"); xdescriptor; xdescriptor = switch_xml_next(xdescriptor)) {
|
||||
const char *name = switch_xml_attr(xdescriptor, "name");
|
||||
const char *tone_name = NULL;
|
||||
switch_xml_t tone = NULL, element = NULL;
|
||||
tone_descriptor_t *descriptor = NULL;
|
||||
|
||||
/* create descriptor */
|
||||
if (zstr(name)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing <descriptor> name\n");
|
||||
switch_goto_status(SWITCH_STATUS_FALSE, done);
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding tone_descriptor: %s\n", name);
|
||||
if (tone_descriptor_create(&descriptor, name, spandsp_globals.config_pool) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to allocate tone_descriptor: %s\n", name);
|
||||
switch_goto_status(SWITCH_STATUS_FALSE, done);
|
||||
}
|
||||
switch_core_hash_insert(spandsp_globals.tones, name, descriptor);
|
||||
|
||||
/* add tones to descriptor */
|
||||
for (tone = switch_xml_child(xdescriptor, "tone"); tone; tone = switch_xml_next(tone)) {
|
||||
int id = 0;
|
||||
tone_name = switch_xml_attr(tone, "name");
|
||||
if (zstr(tone_name)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing <tone> name for <descriptor> %s\n", name);
|
||||
switch_goto_status(SWITCH_STATUS_FALSE, done);
|
||||
}
|
||||
id = tone_descriptor_add_tone(descriptor, tone_name);
|
||||
if (id == -1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
|
||||
"Unable to add tone_descriptor: %s, tone: %s. (too many tones)\n", name, tone_name);
|
||||
switch_goto_status(SWITCH_STATUS_FALSE, done);
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
||||
"Adding tone_descriptor: %s, tone: %s(%d)\n", name, tone_name, id);
|
||||
/* add elements to tone */
|
||||
for (element = switch_xml_child(tone, "element"); element; element = switch_xml_next(element)) {
|
||||
const char *freq1_attr = switch_xml_attr(element, "freq1");
|
||||
const char *freq2_attr = switch_xml_attr(element, "freq2");
|
||||
const char *min_attr = switch_xml_attr(element, "min");
|
||||
const char *max_attr = switch_xml_attr(element, "max");
|
||||
int freq1, freq2, min, max;
|
||||
if (zstr(freq1_attr)) {
|
||||
freq1 = 0;
|
||||
} else {
|
||||
freq1 = atoi(freq1_attr);
|
||||
}
|
||||
if (zstr(freq2_attr)) {
|
||||
freq2 = 0;
|
||||
} else {
|
||||
freq2 = atoi(freq2_attr);
|
||||
}
|
||||
if (zstr(min_attr)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
|
||||
"Missing min in <element> of <descriptor> %s <tone> %s(%d)\n", name, tone_name, id);
|
||||
switch_goto_status(SWITCH_STATUS_FALSE, done);
|
||||
}
|
||||
min = atoi(min_attr);
|
||||
if (zstr(max_attr)) {
|
||||
max = 0;
|
||||
} else {
|
||||
max = atoi(max_attr);
|
||||
}
|
||||
/* check params */
|
||||
if ((freq1 < 0 || freq2 < 0 || min < 0 || max < 0) || (freq1 == 0 && min == 0 && max == 0)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid element param.\n");
|
||||
switch_goto_status(SWITCH_STATUS_FALSE, done);
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
||||
"Adding tone_descriptor: %s, tone: %s(%d), element (%d, %d, %d, %d)\n", name, tone_name, id, freq1, freq2, min, max);
|
||||
tone_descriptor_add_tone_element(descriptor, id, freq1, freq2, min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
switch_xml_free(xml);
|
||||
}
|
||||
|
||||
switch_mutex_unlock(spandsp_globals.mutex);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init)
|
||||
{
|
||||
switch_application_interface_t *app_interface;
|
||||
switch_api_interface_t *api_interface;
|
||||
|
||||
memset(&spandsp_globals, 0, sizeof(spandsp_globals));
|
||||
spandsp_globals.pool = pool;
|
||||
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
switch_mutex_init(&spandsp_globals.mutex, SWITCH_MUTEX_NESTED, pool);
|
||||
|
||||
SWITCH_ADD_APP(app_interface, "t38_gateway", "Convert to T38 Gateway if tones are heard", "Convert to T38 Gateway if tones are heard",
|
||||
t38_gateway_function, "", SAF_MEDIA_TAP);
|
||||
|
@ -284,10 +513,12 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init)
|
|||
|
||||
SWITCH_ADD_APP(app_interface, "spandsp_stop_fax_detect", "stop fax detect", "stop fax detect", spandsp_stop_fax_detect_session_function, "", SAF_NONE);
|
||||
|
||||
load_configuration(0);
|
||||
|
||||
mod_spandsp_fax_load(pool);
|
||||
mod_spandsp_codecs_load(module_interface, pool);
|
||||
|
||||
|
||||
if (mod_spandsp_dsp_load(module_interface, pool) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't load or process spandsp.conf, not adding tone_detect applications\n");
|
||||
} else {
|
||||
|
@ -302,6 +533,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init)
|
|||
/* Not such severe to prevent loading */
|
||||
}
|
||||
|
||||
modem_global_init(module_interface, pool);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "mod_spandsp loaded, using spandsp library version [%s]\n", SPANDSP_RELEASE_DATETIME_STRING);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
@ -313,6 +545,15 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_spandsp_shutdown)
|
|||
|
||||
mod_spandsp_fax_shutdown();
|
||||
mod_spandsp_dsp_shutdown();
|
||||
modem_global_shutdown();
|
||||
|
||||
if (spandsp_globals.tones) {
|
||||
switch_core_hash_destroy(&spandsp_globals.tones);
|
||||
}
|
||||
|
||||
if (spandsp_globals.config_pool) {
|
||||
switch_core_destroy_memory_pool(&spandsp_globals.config_pool);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_UNLOAD;
|
||||
}
|
||||
|
|
|
@ -42,9 +42,40 @@ typedef HANDLE zap_socket_t;
|
|||
typedef int zap_socket_t;
|
||||
#endif
|
||||
|
||||
#define MAX_MODEMS 1024
|
||||
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
|
||||
#include <spandsp.h>
|
||||
|
||||
/* The global stuff */
|
||||
struct spandsp_globals {
|
||||
switch_memory_pool_t *pool;
|
||||
switch_memory_pool_t *config_pool;
|
||||
switch_mutex_t *mutex;
|
||||
|
||||
uint32_t total_sessions;
|
||||
|
||||
short int use_ecm;
|
||||
short int verbose;
|
||||
short int disable_v17;
|
||||
short int enable_t38;
|
||||
short int enable_t38_request;
|
||||
short int enable_t38_insist;
|
||||
char *ident;
|
||||
char *header;
|
||||
char *prepend_string;
|
||||
char *spool;
|
||||
switch_thread_cond_t *cond;
|
||||
switch_mutex_t *cond_mutex;
|
||||
int modem_count;
|
||||
int modem_verbose;
|
||||
char *modem_context;
|
||||
char *modem_dialplan;
|
||||
switch_hash_t *tones;
|
||||
int tonedebug;
|
||||
};
|
||||
|
||||
extern struct spandsp_globals spandsp_globals;
|
||||
|
||||
|
||||
typedef enum {
|
||||
FUNCTION_TX,
|
||||
|
@ -52,6 +83,37 @@ typedef enum {
|
|||
FUNCTION_GW
|
||||
} mod_spandsp_fax_application_mode_t;
|
||||
|
||||
/******************************************************************************
|
||||
* TONE DETECTION WITH CADENCE
|
||||
*/
|
||||
|
||||
#define MAX_TONES 32
|
||||
#define STRLEN 128
|
||||
/**
|
||||
* Tone descriptor
|
||||
*
|
||||
* Defines a set of tones to look for
|
||||
*/
|
||||
struct tone_descriptor {
|
||||
/** The name of this descriptor set */
|
||||
const char *name;
|
||||
|
||||
/** Describes the tones to watch */
|
||||
super_tone_rx_descriptor_t *spandsp_tone_descriptor;
|
||||
|
||||
/** The mapping of tone id to key */
|
||||
char tone_keys[MAX_TONES][STRLEN];
|
||||
int idx;
|
||||
|
||||
};
|
||||
typedef struct tone_descriptor tone_descriptor_t;
|
||||
|
||||
|
||||
switch_status_t tone_descriptor_create(tone_descriptor_t **descriptor, const char *name, switch_memory_pool_t *memory_pool);
|
||||
int tone_descriptor_add_tone(tone_descriptor_t *descriptor, const char *name);
|
||||
switch_status_t tone_descriptor_add_tone_element(tone_descriptor_t *descriptor, int tone_id, int freq1, int freq2, int min, int max);
|
||||
|
||||
|
||||
void mod_spandsp_fax_load(switch_memory_pool_t *pool);
|
||||
switch_status_t mod_spandsp_codecs_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool);
|
||||
switch_status_t mod_spandsp_dsp_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool);
|
||||
|
@ -74,3 +136,5 @@ switch_status_t spandsp_fax_detect_session(switch_core_session_t *session,
|
|||
int hits, const char *app, const char *data, switch_tone_detect_callback_t callback);
|
||||
|
||||
switch_status_t spandsp_fax_stop_detect_session(switch_core_session_t *session);
|
||||
void spanfax_log_message(int level, const char *msg);
|
||||
switch_status_t load_configuration(switch_bool_t reload);
|
||||
|
|
|
@ -155,48 +155,7 @@ switch_status_t spandsp_inband_dtmf_session(switch_core_session_t *session)
|
|||
/* private channel data */
|
||||
#define TONE_PRIVATE "mod_tone_detect_bug"
|
||||
|
||||
/**
|
||||
* Module global variables
|
||||
*/
|
||||
struct globals {
|
||||
/** Memory pool */
|
||||
switch_memory_pool_t *pool;
|
||||
/** Call progress tones mapped by descriptor name */
|
||||
switch_hash_t *tones;
|
||||
/** Default debug level */
|
||||
int debug;
|
||||
};
|
||||
typedef struct globals globals_t;
|
||||
static globals_t globals;
|
||||
|
||||
/******************************************************************************
|
||||
* TONE DETECTION WITH CADENCE
|
||||
*/
|
||||
|
||||
#define MAX_TONES 32
|
||||
#define STRLEN 128
|
||||
/**
|
||||
* Tone descriptor
|
||||
*
|
||||
* Defines a set of tones to look for
|
||||
*/
|
||||
struct tone_descriptor {
|
||||
/** The name of this descriptor set */
|
||||
const char *name;
|
||||
|
||||
/** Describes the tones to watch */
|
||||
super_tone_rx_descriptor_t *spandsp_tone_descriptor;
|
||||
|
||||
/** The mapping of tone id to key */
|
||||
char tone_keys[MAX_TONES][STRLEN];
|
||||
int idx;
|
||||
|
||||
};
|
||||
typedef struct tone_descriptor tone_descriptor_t;
|
||||
|
||||
static switch_status_t tone_descriptor_create(tone_descriptor_t **descriptor, const char *name, switch_memory_pool_t *memory_pool);
|
||||
static int tone_descriptor_add_tone(tone_descriptor_t *descriptor, const char *name);
|
||||
static switch_status_t tone_descriptor_add_tone_element(tone_descriptor_t *descriptor, int tone_id, int freq1, int freq2, int min, int max);
|
||||
|
||||
/**
|
||||
* Tone detector
|
||||
|
@ -232,7 +191,7 @@ static switch_bool_t callprogress_detector_process_buffer(switch_media_bug_t *bu
|
|||
* @param memory_pool the pool to use
|
||||
* @return SWITCH_STATUS_SUCCESS if successful
|
||||
*/
|
||||
static switch_status_t tone_descriptor_create(tone_descriptor_t **descriptor, const char *name, switch_memory_pool_t *memory_pool)
|
||||
switch_status_t tone_descriptor_create(tone_descriptor_t **descriptor, const char *name, switch_memory_pool_t *memory_pool)
|
||||
{
|
||||
tone_descriptor_t *ldescriptor = NULL;
|
||||
ldescriptor = switch_core_alloc(memory_pool, sizeof(tone_descriptor_t));
|
||||
|
@ -253,7 +212,7 @@ static switch_status_t tone_descriptor_create(tone_descriptor_t **descriptor, co
|
|||
* @param key the tone key - this will be returned by the detector upon match
|
||||
* @return the tone ID
|
||||
*/
|
||||
static int tone_descriptor_add_tone(tone_descriptor_t *descriptor, const char *key)
|
||||
int tone_descriptor_add_tone(tone_descriptor_t *descriptor, const char *key)
|
||||
{
|
||||
int id = super_tone_rx_add_tone(descriptor->spandsp_tone_descriptor);
|
||||
if (id >= MAX_TONES) {
|
||||
|
@ -279,7 +238,7 @@ static int tone_descriptor_add_tone(tone_descriptor_t *descriptor, const char *k
|
|||
* @param max the maximum tone duration in ms
|
||||
* @return SWITCH_STATUS_SUCCESS if successful
|
||||
*/
|
||||
static switch_status_t tone_descriptor_add_tone_element(tone_descriptor_t *descriptor, int tone_id, int freq1, int freq2, int min, int max)
|
||||
switch_status_t tone_descriptor_add_tone_element(tone_descriptor_t *descriptor, int tone_id, int freq1, int freq2, int min, int max)
|
||||
{
|
||||
if (super_tone_rx_add_element(descriptor->spandsp_tone_descriptor, tone_id, freq1, freq2, min, max) == 0) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
@ -337,7 +296,7 @@ static switch_status_t tone_detector_create(tone_detector_t **detector, tone_des
|
|||
}
|
||||
memset(ldetector, 0, sizeof(tone_detector_t));
|
||||
ldetector->descriptor = descriptor;
|
||||
ldetector->debug = globals.debug;
|
||||
ldetector->debug = spandsp_globals.tonedebug;
|
||||
*detector = ldetector;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -409,7 +368,7 @@ switch_status_t callprogress_detector_start(switch_core_session_t *session, cons
|
|||
}
|
||||
|
||||
/* find the tone descriptor with the matching name and create the detector */
|
||||
descriptor = switch_core_hash_find(globals.tones, name);
|
||||
descriptor = switch_core_hash_find(spandsp_globals.tones, name);
|
||||
if (!descriptor) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "(%s) no tone descriptor defined with name '%s'. Update configuration. \n", switch_channel_get_name(channel), name);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
|
@ -509,116 +468,11 @@ switch_status_t callprogress_detector_stop(switch_core_session_t *session)
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process configuration file
|
||||
*/
|
||||
static switch_status_t do_config(void)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
switch_xml_t cfg = NULL, xml = NULL, callprogress = NULL, xdescriptor = NULL;
|
||||
if (!(xml = switch_xml_open_cfg("spandsp.conf", &cfg, NULL))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not open spandsp.conf\n");
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* TODO make configuration param */
|
||||
globals.debug = 1;
|
||||
|
||||
/* Configure call progress detector */
|
||||
if ((callprogress = switch_xml_child(cfg, "descriptors"))) {
|
||||
for (xdescriptor = switch_xml_child(callprogress, "descriptor"); xdescriptor; xdescriptor = switch_xml_next(xdescriptor)) {
|
||||
const char *name = switch_xml_attr(xdescriptor, "name");
|
||||
const char *tone_name = NULL;
|
||||
switch_xml_t tone = NULL, element = NULL;
|
||||
tone_descriptor_t *descriptor = NULL;
|
||||
|
||||
/* create descriptor */
|
||||
if (zstr(name)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing <descriptor> name\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding tone_descriptor: %s\n", name);
|
||||
if (tone_descriptor_create(&descriptor, name, globals.pool) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to allocate tone_descriptor: %s\n", name);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
switch_core_hash_insert(globals.tones, name, descriptor);
|
||||
|
||||
/* add tones to descriptor */
|
||||
for (tone = switch_xml_child(xdescriptor, "tone"); tone; tone = switch_xml_next(tone)) {
|
||||
int id = 0;
|
||||
tone_name = switch_xml_attr(tone, "name");
|
||||
if (zstr(tone_name)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing <tone> name for <descriptor> %s\n", name);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
id = tone_descriptor_add_tone(descriptor, tone_name);
|
||||
if (id == -1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to add tone_descriptor: %s, tone: %s. (too many tones)\n", name, tone_name);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding tone_descriptor: %s, tone: %s(%d)\n", name, tone_name, id);
|
||||
/* add elements to tone */
|
||||
for (element = switch_xml_child(tone, "element"); element; element = switch_xml_next(element)) {
|
||||
const char *freq1_attr = switch_xml_attr(element, "freq1");
|
||||
const char *freq2_attr = switch_xml_attr(element, "freq2");
|
||||
const char *min_attr = switch_xml_attr(element, "min");
|
||||
const char *max_attr = switch_xml_attr(element, "max");
|
||||
int freq1, freq2, min, max;
|
||||
if (zstr(freq1_attr)) {
|
||||
freq1 = 0;
|
||||
} else {
|
||||
freq1 = atoi(freq1_attr);
|
||||
}
|
||||
if (zstr(freq2_attr)) {
|
||||
freq2 = 0;
|
||||
} else {
|
||||
freq2 = atoi(freq2_attr);
|
||||
}
|
||||
if (zstr(min_attr)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing min in <element> of <descriptor> %s <tone> %s(%d)\n", name, tone_name, id);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
min = atoi(min_attr);
|
||||
if (zstr(max_attr)) {
|
||||
max = 0;
|
||||
} else {
|
||||
max = atoi(max_attr);
|
||||
}
|
||||
/* check params */
|
||||
if ((freq1 < 0 || freq2 < 0 || min < 0 || max < 0) || (freq1 == 0 && min == 0 && max == 0)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid element param.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding tone_descriptor: %s, tone: %s(%d), element (%d, %d, %d, %d)\n", name, tone_name, id, freq1, freq2, min, max);
|
||||
tone_descriptor_add_tone_element(descriptor, id, freq1, freq2, min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (xml) {
|
||||
switch_xml_free(xml);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when FreeSWITCH loads the module
|
||||
*/
|
||||
switch_status_t mod_spandsp_dsp_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool)
|
||||
{
|
||||
memset(&globals, 0, sizeof(globals_t));
|
||||
globals.pool = pool;
|
||||
|
||||
switch_core_hash_init(&globals.tones, globals.pool);
|
||||
if (do_config() != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* indicate that the module should continue to be loaded */
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -628,7 +482,7 @@ switch_status_t mod_spandsp_dsp_load(switch_loadable_module_interface_t **module
|
|||
*/
|
||||
void mod_spandsp_dsp_shutdown(void)
|
||||
{
|
||||
switch_core_hash_destroy(&globals.tones);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -60,26 +60,6 @@ typedef enum {
|
|||
T38_MODE_REFUSED = -1,
|
||||
} t38_mode_t;
|
||||
|
||||
/* The global stuff */
|
||||
static struct {
|
||||
switch_memory_pool_t *pool;
|
||||
switch_mutex_t *mutex;
|
||||
|
||||
uint32_t total_sessions;
|
||||
|
||||
short int use_ecm;
|
||||
short int verbose;
|
||||
short int disable_v17;
|
||||
short int enable_t38;
|
||||
short int enable_t38_request;
|
||||
short int enable_t38_insist;
|
||||
char ident[20];
|
||||
char header[50];
|
||||
char *prepend_string;
|
||||
char *spool;
|
||||
switch_thread_cond_t *cond;
|
||||
switch_mutex_t *cond_mutex;
|
||||
} globals;
|
||||
|
||||
struct pvt_s {
|
||||
switch_core_session_t *session;
|
||||
|
@ -128,13 +108,13 @@ static struct {
|
|||
static void wake_thread(int force)
|
||||
{
|
||||
if (force) {
|
||||
switch_thread_cond_signal(globals.cond);
|
||||
switch_thread_cond_signal(spandsp_globals.cond);
|
||||
return;
|
||||
}
|
||||
|
||||
if (switch_mutex_trylock(globals.cond_mutex) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_thread_cond_signal(globals.cond);
|
||||
switch_mutex_unlock(globals.cond_mutex);
|
||||
if (switch_mutex_trylock(spandsp_globals.cond_mutex) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_thread_cond_signal(spandsp_globals.cond);
|
||||
switch_mutex_unlock(spandsp_globals.cond_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,7 +186,7 @@ static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *
|
|||
goto end;
|
||||
}
|
||||
|
||||
switch_mutex_lock(globals.cond_mutex);
|
||||
switch_mutex_lock(spandsp_globals.cond_mutex);
|
||||
|
||||
while(t38_state_list.thread_running) {
|
||||
|
||||
|
@ -214,7 +194,7 @@ static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *
|
|||
|
||||
if (!t38_state_list.head) {
|
||||
switch_mutex_unlock(t38_state_list.mutex);
|
||||
switch_thread_cond_wait(globals.cond, globals.cond_mutex);
|
||||
switch_thread_cond_wait(spandsp_globals.cond, spandsp_globals.cond_mutex);
|
||||
switch_core_timer_sync(&timer);
|
||||
continue;
|
||||
}
|
||||
|
@ -230,7 +210,7 @@ static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *
|
|||
switch_core_timer_next(&timer);
|
||||
}
|
||||
|
||||
switch_mutex_unlock(globals.cond_mutex);
|
||||
switch_mutex_unlock(spandsp_globals.cond_mutex);
|
||||
|
||||
end:
|
||||
|
||||
|
@ -252,9 +232,9 @@ static void launch_timer_thread(void)
|
|||
|
||||
switch_threadattr_t *thd_attr = NULL;
|
||||
|
||||
switch_threadattr_create(&thd_attr, globals.pool);
|
||||
switch_threadattr_create(&thd_attr, spandsp_globals.pool);
|
||||
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
||||
switch_thread_create(&t38_state_list.thread, thd_attr, timer_thread_run, NULL, globals.pool);
|
||||
switch_thread_create(&t38_state_list.thread, thd_attr, timer_thread_run, NULL, spandsp_globals.pool);
|
||||
}
|
||||
|
||||
|
||||
|
@ -264,12 +244,12 @@ static void launch_timer_thread(void)
|
|||
|
||||
static void counter_increment(void)
|
||||
{
|
||||
switch_mutex_lock(globals.mutex);
|
||||
globals.total_sessions++;
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
switch_mutex_lock(spandsp_globals.mutex);
|
||||
spandsp_globals.total_sessions++;
|
||||
switch_mutex_unlock(spandsp_globals.mutex);
|
||||
}
|
||||
|
||||
static void spanfax_log_message(int level, const char *msg)
|
||||
void spanfax_log_message(int level, const char *msg)
|
||||
{
|
||||
int fs_log_level;
|
||||
|
||||
|
@ -821,7 +801,7 @@ static t38_mode_t negotiate_t38(pvt_t *pvt)
|
|||
} else if ((v = switch_channel_get_variable(channel, "fax_enable_t38"))) {
|
||||
enabled = switch_true(v);
|
||||
} else {
|
||||
enabled = globals.enable_t38;
|
||||
enabled = spandsp_globals.enable_t38;
|
||||
}
|
||||
|
||||
if (!(enabled && t38_options)) {
|
||||
|
@ -877,7 +857,7 @@ static t38_mode_t negotiate_t38(pvt_t *pvt)
|
|||
if ((v = switch_channel_get_variable(channel, "fax_enable_t38_insist"))) {
|
||||
insist = switch_true(v);
|
||||
} else {
|
||||
insist = globals.enable_t38_insist;
|
||||
insist = spandsp_globals.enable_t38_insist;
|
||||
}
|
||||
|
||||
/* This will send the options back in a response */
|
||||
|
@ -907,14 +887,14 @@ static t38_mode_t request_t38(pvt_t *pvt)
|
|||
} else if ((v = switch_channel_get_variable(channel, "fax_enable_t38"))) {
|
||||
enabled = switch_true(v);
|
||||
} else {
|
||||
enabled = globals.enable_t38;
|
||||
enabled = spandsp_globals.enable_t38;
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
if ((v = switch_channel_get_variable(channel, "fax_enable_t38_request"))) {
|
||||
enabled = switch_true(v);
|
||||
} else {
|
||||
enabled = globals.enable_t38_request;
|
||||
enabled = spandsp_globals.enable_t38_request;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -922,7 +902,7 @@ static t38_mode_t request_t38(pvt_t *pvt)
|
|||
if ((v = switch_channel_get_variable(channel, "fax_enable_t38_insist"))) {
|
||||
insist = switch_true(v);
|
||||
} else {
|
||||
insist = globals.enable_t38_insist;
|
||||
insist = spandsp_globals.enable_t38_insist;
|
||||
}
|
||||
|
||||
if ((t38_options = switch_channel_get_private(channel, "t38_options"))) {
|
||||
|
@ -1004,19 +984,19 @@ static pvt_t *pvt_init(switch_core_session_t *session, mod_spandsp_fax_applicati
|
|||
if ((tmp = switch_channel_get_variable(channel, "fax_use_ecm"))) {
|
||||
pvt->use_ecm = switch_true(tmp);
|
||||
} else {
|
||||
pvt->use_ecm = globals.use_ecm;
|
||||
pvt->use_ecm = spandsp_globals.use_ecm;
|
||||
}
|
||||
|
||||
if ((tmp = switch_channel_get_variable(channel, "fax_disable_v17"))) {
|
||||
pvt->disable_v17 = switch_true(tmp);
|
||||
} else {
|
||||
pvt->disable_v17 = globals.disable_v17;
|
||||
pvt->disable_v17 = spandsp_globals.disable_v17;
|
||||
}
|
||||
|
||||
if ((tmp = switch_channel_get_variable(channel, "fax_verbose"))) {
|
||||
pvt->verbose = switch_true(tmp);
|
||||
} else {
|
||||
pvt->verbose = globals.verbose;
|
||||
pvt->verbose = spandsp_globals.verbose;
|
||||
}
|
||||
|
||||
if ((tmp = switch_channel_get_variable(channel, "fax_force_caller"))) {
|
||||
|
@ -1036,7 +1016,7 @@ static pvt_t *pvt_init(switch_core_session_t *session, mod_spandsp_fax_applicati
|
|||
|
||||
switch_safe_free(data);
|
||||
} else {
|
||||
pvt->ident = switch_core_session_strdup(session, globals.ident);
|
||||
pvt->ident = switch_core_session_strdup(session, spandsp_globals.ident);
|
||||
}
|
||||
|
||||
if ((tmp = switch_channel_get_variable(channel, "fax_header"))) {
|
||||
|
@ -1048,7 +1028,7 @@ static pvt_t *pvt_init(switch_core_session_t *session, mod_spandsp_fax_applicati
|
|||
|
||||
switch_safe_free(data);
|
||||
} else {
|
||||
pvt->header = switch_core_session_strdup(session, globals.header);
|
||||
pvt->header = switch_core_session_strdup(session, spandsp_globals.header);
|
||||
}
|
||||
|
||||
if (pvt->app_mode == FUNCTION_TX) {
|
||||
|
@ -1118,10 +1098,10 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
|
|||
time = switch_time_now();
|
||||
|
||||
if (!(prefix = switch_channel_get_variable(channel, "fax_prefix"))) {
|
||||
prefix = globals.prepend_string;
|
||||
prefix = spandsp_globals.prepend_string;
|
||||
}
|
||||
|
||||
if (!(pvt->filename = switch_core_session_sprintf(session, "%s/%s-%ld-%ld.tif", globals.spool, prefix, globals.total_sessions, time))) {
|
||||
if (!(pvt->filename = switch_core_session_sprintf(session, "%s/%s-%ld-%ld.tif", spandsp_globals.spool, prefix, spandsp_globals.total_sessions, time))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot automatically set fax RX destination file\n");
|
||||
goto done;
|
||||
}
|
||||
|
@ -1338,107 +1318,17 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
|
|||
}
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
CONFIGURATION
|
||||
************************************************************************* */
|
||||
|
||||
void load_configuration(switch_bool_t reload)
|
||||
{
|
||||
switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL;
|
||||
|
||||
if ((xml = switch_xml_open_cfg("fax.conf", &cfg, NULL))) {
|
||||
if ((x_lists = switch_xml_child(cfg, "settings"))) {
|
||||
for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {
|
||||
const char *name = switch_xml_attr(x_list, "name");
|
||||
const char *value = switch_xml_attr(x_list, "value");
|
||||
|
||||
if (zstr(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (zstr(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(name, "use-ecm")) {
|
||||
if (switch_true(value))
|
||||
globals.use_ecm = 1;
|
||||
else
|
||||
globals.use_ecm = 0;
|
||||
} else if (!strcmp(name, "verbose")) {
|
||||
if (switch_true(value))
|
||||
globals.verbose = 1;
|
||||
else
|
||||
globals.verbose = 0;
|
||||
} else if (!strcmp(name, "disable-v17")) {
|
||||
if (switch_true(value))
|
||||
globals.disable_v17 = 1;
|
||||
else
|
||||
globals.disable_v17 = 0;
|
||||
} else if (!strcmp(name, "enable-t38")) {
|
||||
if (switch_true(value)) {
|
||||
globals.enable_t38= 1;
|
||||
} else {
|
||||
globals.enable_t38 = 0;
|
||||
}
|
||||
} else if (!strcmp(name, "enable-t38-request")) {
|
||||
if (switch_true(value)) {
|
||||
globals.enable_t38_request = 1;
|
||||
} else {
|
||||
globals.enable_t38_request = 0;
|
||||
}
|
||||
} else if (!strcmp(name, "ident")) {
|
||||
strncpy(globals.ident, value, sizeof(globals.ident) - 1);
|
||||
} else if (!strcmp(name, "header")) {
|
||||
strncpy(globals.header, value, sizeof(globals.header) - 1);
|
||||
} else if (!strcmp(name, "spool-dir")) {
|
||||
globals.spool = switch_core_strdup(globals.pool, value);
|
||||
} else if (!strcmp(name, "file-prefix")) {
|
||||
globals.prepend_string = switch_core_strdup(globals.pool, value);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown parameter %s\n", name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
switch_xml_free(xml);
|
||||
}
|
||||
}
|
||||
|
||||
void mod_spandsp_fax_event_handler(switch_event_t *event)
|
||||
{
|
||||
load_configuration(1);
|
||||
}
|
||||
|
||||
|
||||
void mod_spandsp_fax_load(switch_memory_pool_t *pool)
|
||||
{
|
||||
uint32_t sanity = 200;
|
||||
|
||||
memset(&globals, 0, sizeof(globals));
|
||||
memset(&t38_state_list, 0, sizeof(t38_state_list));
|
||||
|
||||
globals.pool = pool;
|
||||
|
||||
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
|
||||
switch_mutex_init(&t38_state_list.mutex, SWITCH_MUTEX_NESTED, globals.pool);
|
||||
|
||||
switch_mutex_init(&globals.cond_mutex, SWITCH_MUTEX_NESTED, globals.pool);
|
||||
switch_thread_cond_create(&globals.cond, globals.pool);
|
||||
|
||||
globals.enable_t38 = 1;
|
||||
globals.total_sessions = 0;
|
||||
globals.verbose = 1;
|
||||
globals.use_ecm = 1;
|
||||
globals.disable_v17 = 0;
|
||||
globals.prepend_string = switch_core_strdup(globals.pool, "fax");
|
||||
globals.spool = switch_core_strdup(globals.pool, "/tmp");
|
||||
strncpy(globals.ident, "SpanDSP Fax Ident", sizeof(globals.ident) - 1);
|
||||
strncpy(globals.header, "SpanDSP Fax Header", sizeof(globals.header) - 1);
|
||||
|
||||
load_configuration(0);
|
||||
switch_mutex_init(&spandsp_globals.mutex, SWITCH_MUTEX_NESTED, spandsp_globals.pool);
|
||||
switch_mutex_init(&t38_state_list.mutex, SWITCH_MUTEX_NESTED, spandsp_globals.pool);
|
||||
|
||||
switch_mutex_init(&spandsp_globals.cond_mutex, SWITCH_MUTEX_NESTED, spandsp_globals.pool);
|
||||
switch_thread_cond_create(&spandsp_globals.cond, spandsp_globals.pool);
|
||||
|
||||
launch_timer_thread();
|
||||
|
||||
|
@ -1454,7 +1344,7 @@ void mod_spandsp_fax_shutdown(void)
|
|||
t38_state_list.thread_running = 0;
|
||||
wake_thread(1);
|
||||
switch_thread_join(&tstatus, t38_state_list.thread);
|
||||
memset(&globals, 0, sizeof(globals));
|
||||
memset(&spandsp_globals, 0, sizeof(spandsp_globals));
|
||||
}
|
||||
|
||||
static const switch_state_handler_table_t t38_gateway_state_handlers;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH mod_fax.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Massimo Cetra <devel@navynet.it>
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Brian West <brian@freeswitch.org>
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Steve Underwood <steveu@coppice.org>
|
||||
* mod_spandsp_modem.h -- Fax modem applications provided by SpanDSP
|
||||
*
|
||||
*/
|
||||
|
||||
#include "switch_private.h"
|
||||
#if defined(HAVE_OPENPTY) || defined(HAVE_DEV_PTMX) || defined(HAVE_POSIX_OPENPT)
|
||||
#define MODEM_SUPPORT 1
|
||||
#if !defined(HAVE_POSIX_OPENPT) && !defined(HAVE_DEV_PTMX)
|
||||
#define USE_OPENPTY 1
|
||||
#endif
|
||||
#ifndef _MOD_SPANDSP_MODEM_H
|
||||
#define _MOD_SPANDSP_MODEM_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pty.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <byteswap.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdint.h>
|
||||
#include <tiffio.h>
|
||||
#include <spandsp.h>
|
||||
|
||||
|
||||
typedef enum {
|
||||
MODEM_STATE_INIT,
|
||||
MODEM_STATE_ONHOOK,
|
||||
MODEM_STATE_OFFHOOK,
|
||||
MODEM_STATE_ACQUIRED,
|
||||
MODEM_STATE_RINGING,
|
||||
MODEM_STATE_ANSWERED,
|
||||
MODEM_STATE_DIALING,
|
||||
MODEM_STATE_CONNECTED,
|
||||
MODEM_STATE_HANGUP,
|
||||
MODEM_STATE_LAST
|
||||
} modem_state_t;
|
||||
|
||||
struct modem;
|
||||
|
||||
typedef int (*modem_control_handler_t)(struct modem *, const char *, int);
|
||||
|
||||
|
||||
typedef enum {
|
||||
MODEM_FLAG_RUNNING = ( 1 << 0),
|
||||
MODEM_FLAG_XOFF = ( 1 << 1)
|
||||
} modem_flags;
|
||||
|
||||
struct modem {
|
||||
t31_state_t *t31_state;
|
||||
char digits[512];
|
||||
modem_flags flags;
|
||||
int master;
|
||||
int slave;
|
||||
char *stty;
|
||||
char devlink[128];
|
||||
int id;
|
||||
modem_state_t state;
|
||||
modem_control_handler_t control_handler;
|
||||
void *user_data;
|
||||
switch_mutex_t *mutex;
|
||||
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
|
||||
switch_time_t last_event;
|
||||
int slot;
|
||||
};
|
||||
|
||||
typedef struct modem modem_t;
|
||||
|
||||
char *modem_state2name(int state);
|
||||
int modem_close(struct modem *fm);
|
||||
int modem_init(struct modem *fm, modem_control_handler_t control_handler);
|
||||
|
||||
#endif //MODEM_SUPPORT
|
||||
|
||||
switch_status_t modem_global_init(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool);
|
||||
void modem_global_shutdown(void);
|
||||
|
||||
#endif //_MOD_SPANDSP_MODEM_H
|
Loading…
Reference in New Issue