diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln index 4148d2ddc5..37ba5cfac0 100644 --- a/Freeswitch.2010.sln +++ b/Freeswitch.2010.sln @@ -572,6 +572,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcbt", "libs\win32\libcbt EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_cielab_luts", "libs\spandsp\src\msvc\make_cielab_luts.2010.vcxproj", "{85F0CF8C-C7AB-48F6-BA19-CC94CF87F981}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_t43_gray_code_tables", "libs\spandsp\src\msvc\make_t43_gray_code_tables.2010.vcxproj", "{EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution All|Win32 = All|Win32 @@ -3810,6 +3812,23 @@ Global {85F0CF8C-C7AB-48F6-BA19-CC94CF87F981}.Release|x64.Build.0 = All|Win32 {85F0CF8C-C7AB-48F6-BA19-CC94CF87F981}.Release|x64 Setup.ActiveCfg = All|Win32 {85F0CF8C-C7AB-48F6-BA19-CC94CF87F981}.Release|x86 Setup.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.All|Win32.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.All|Win32.Build.0 = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.All|x64.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.All|x64 Setup.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.All|x86 Setup.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Debug|Win32.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Debug|Win32.Build.0 = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Debug|x64.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Debug|x64.Build.0 = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Debug|x64 Setup.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Debug|x86 Setup.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|Win32.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|Win32.Build.0 = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x64.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x64.Build.0 = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x64 Setup.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x86 Setup.ActiveCfg = All|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3927,6 +3946,7 @@ Global {9D04A840-CE18-4FF5-A6D3-0A2BB92FF2E6} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {77BC1DD2-C9A1-44D7-BFFA-1320370CACB9} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {85F0CF8C-C7AB-48F6-BA19-CC94CF87F981} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {EC3E5C7F-EE09-47E2-80FE-546363D14A98} = {B8F5B47B-8568-46EB-B320-64C17D2A98BC} {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F} = {0C808854-54D1-4230-BFF5-77B5FD905000} {ACFFF684-4D19-4D48-AF12-88EA1D778BDF} = {0C808854-54D1-4230-BFF5-77B5FD905000} diff --git a/Freeswitch.2012.sln b/Freeswitch.2012.sln index 346914e690..be88964420 100644 --- a/Freeswitch.2012.sln +++ b/Freeswitch.2012.sln @@ -577,6 +577,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcbt", "libs\win32\libcbt EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_cielab_luts", "libs\spandsp\src\msvc\make_cielab_luts.2012.vcxproj", "{85F0CF8C-C7AB-48F6-BA19-CC94CF87F981}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_t43_gray_code_tables", "libs\spandsp\src\msvc\make_t43_gray_code_tables.2012.vcxproj", "{EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution All|Win32 = All|Win32 @@ -3820,6 +3822,23 @@ Global {85F0CF8C-C7AB-48F6-BA19-CC94CF87F981}.Release|x64.Build.0 = All|Win32 {85F0CF8C-C7AB-48F6-BA19-CC94CF87F981}.Release|x64 Setup.ActiveCfg = All|Win32 {85F0CF8C-C7AB-48F6-BA19-CC94CF87F981}.Release|x86 Setup.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.All|Win32.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.All|Win32.Build.0 = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.All|x64.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.All|x64 Setup.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.All|x86 Setup.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Debug|Win32.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Debug|Win32.Build.0 = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Debug|x64.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Debug|x64.Build.0 = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Debug|x64 Setup.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Debug|x86 Setup.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|Win32.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|Win32.Build.0 = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x64.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x64.Build.0 = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x64 Setup.ActiveCfg = All|Win32 + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x86 Setup.ActiveCfg = All|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3937,6 +3956,7 @@ Global {2386B892-35F5-46CF-A0F0-10394D2FBF9B} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {77BC1DD2-C9A1-44D7-BFFA-1320370CACB9} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {85F0CF8C-C7AB-48F6-BA19-CC94CF87F981} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {EC3E5C7F-EE09-47E2-80FE-546363D14A98} = {B8F5B47B-8568-46EB-B320-64C17D2A98BC} {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F} = {0C808854-54D1-4230-BFF5-77B5FD905000} {ACFFF684-4D19-4D48-AF12-88EA1D778BDF} = {0C808854-54D1-4230-BFF5-77B5FD905000} diff --git a/libs/esl/src/esl_event.c b/libs/esl/src/esl_event.c index 163d35cc6c..b5a6be4d58 100644 --- a/libs/esl/src/esl_event.c +++ b/libs/esl/src/esl_event.c @@ -98,8 +98,6 @@ static const char *EVENT_NAMES[] = { "MESSAGE", "PRESENCE_IN", "NOTIFY_IN", - "PHONE_FEATURE", - "PHONE_FEATURE_SUBSCRIBE", "PRESENCE_OUT", "PRESENCE_PROBE", "MESSAGE_WAITING", @@ -118,6 +116,8 @@ static const char *EVENT_NAMES[] = { "RE_SCHEDULE", "RELOADXML", "NOTIFY", + "PHONE_FEATURE", + "PHONE_FEATURE_SUBSCRIBE", "SEND_MESSAGE", "RECV_MESSAGE", "REQUEST_PARAMS", diff --git a/libs/esl/src/include/esl_event.h b/libs/esl/src/include/esl_event.h index 0bf9259a37..44cfd184dc 100644 --- a/libs/esl/src/include/esl_event.h +++ b/libs/esl/src/include/esl_event.h @@ -106,6 +106,8 @@ typedef enum { ESL_EVENT_RE_SCHEDULE, ESL_EVENT_RELOADXML, ESL_EVENT_NOTIFY, + ESL_EVENT_PHONE_FEATURE, + ESL_EVENT_PHONE_FEATURE_SUBSCRIBE, ESL_EVENT_SEND_MESSAGE, ESL_EVENT_RECV_MESSAGE, ESL_EVENT_REQUEST_PARAMS, @@ -117,6 +119,7 @@ typedef enum { ESL_EVENT_SERVER_DISCONNECTED, ESL_EVENT_SEND_INFO, ESL_EVENT_RECV_INFO, + ESL_EVENT_RECV_RTCP_MESSAGE, ESL_EVENT_CALL_SECURE, ESL_EVENT_NAT, ESL_EVENT_RECORD_START, diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 63ebb2503b..ae76496397 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Fri Aug 23 04:09:44 CDT 2013 +Thu Sep 5 20:55:45 CDT 2013 diff --git a/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c b/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c index b587aa5cc1..537e9fe606 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c +++ b/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c @@ -618,8 +618,10 @@ static void print_media(sdp_printer_t *p, sdp_printf(p, " %s", l->l_text); } else { - sdp_printf(p, " 19"); /* SDP syntax requires at least one format. - 19 is used by nobody, right?. */ + /* SDP syntax requires at least one format. */ + /* defaults to "19", or "t38" for image */ + if (m->m_type == sdp_media_image) sdp_printf(p, " t38"); + else sdp_printf(p, " 19"); } diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c index 6d0c750fd4..1f16d0f18c 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c @@ -435,6 +435,9 @@ int tport_ws_init_secondary(tport_t *self, int socket, int accepted, self->tp_has_connection = 1; + /* override the default 30 minute timeout on tport connections */ + self->tp_params->tpp_idle = UINT_MAX; + if (setsockopt(socket, SOL_TCP, TCP_NODELAY, (void *)&one, sizeof one) == -1) return *return_reason = "TCP_NODELAY", -1; diff --git a/libs/spandsp/Makefile.am b/libs/spandsp/Makefile.am index 3eaddfc7a1..6902c867c5 100644 --- a/libs/spandsp/Makefile.am +++ b/libs/spandsp/Makefile.am @@ -47,7 +47,8 @@ EXTRA_DIST = autogen.sh \ unpack_g726_data.sh \ unpack_gsm0610_data.sh \ unpack_v56ter_data.sh \ - wrapper.xsl + wrapper.xsl \ + yum-prepare.sh if COND_DOC MAYBE_DOC=doc diff --git a/libs/spandsp/configure.ac b/libs/spandsp/configure.ac index 13e31152a4..de395ec4cc 100644 --- a/libs/spandsp/configure.ac +++ b/libs/spandsp/configure.ac @@ -19,7 +19,7 @@ # @start 1 AC_PREREQ([2.59]) -AC_INIT([spandsp], [0.0.7]) +AC_INIT([spandsp], [1.99.0]) SPANDSP_LT_CURRENT=3 SPANDSP_LT_REVISION=0 @@ -125,6 +125,9 @@ AC_TYPE_SIGNAL AC_ARG_ENABLE(doc, [ --enable-doc Build the documentation]) AC_ARG_ENABLE(tests, [ --enable-tests Build the test programs]) +AC_ARG_ENABLE(t43, [ --enable-t43 Enable T.43 support]) +AC_ARG_ENABLE(v32bis, [ --enable-v32bis Enable V.32bis support]) +AC_ARG_ENABLE(v34, [ --enable-v34 Enable V.34 support]) AC_ARG_ENABLE(mmx, [ --enable-mmx Enable MMX support]) AC_ARG_ENABLE(sse, [ --enable-sse Enable SSE support]) AC_ARG_ENABLE(sse2, [ --enable-sse2 Enable SSE2 support]) @@ -265,15 +268,6 @@ then esac fi -AC_DEFINE([SPANDSP_SUPPORT_T42], [1], [Support T.42 JPEG compression]) -SPANDSP_SUPPORT_T42="#define SPANDSP_SUPPORT_T42 1" -AC_DEFINE([SPANDSP_SUPPORT_T43], [1], [Support T.43 JBIG gray and colour compression]) -SPANDSP_SUPPORT_T43="#define SPANDSP_SUPPORT_T43 1" -#AC_DEFINE([SPANDSP_SUPPORT_V32BIS], [1], [Support the V.32bis modem]) -SPANDSP_SUPPORT_V32BIS="#undef SPANDSP_SUPPORT_V32BIS" -#AC_DEFINE([SPANDSP_SUPPORT_V34], [1], [Support the V.34 FAX modem]) -SPANDSP_SUPPORT_V34="#undef SPANDSP_SUPPORT_V34" - AC_CHECK_LIB([m], [cos]) # Some platforms still seem to lack the basic single precision trig and power related functions. AC_SEARCH_LIBS([sinf], [m], AC_DEFINE([HAVE_SINF], [1], [Define to 1 if you have the sinf() function.])) @@ -524,21 +518,6 @@ x86_64-* | i386-* | i686-*) ;; esac -AM_CONDITIONAL([COND_DOC], [test "$enable_doc" = yes]) -AM_CONDITIONAL([COND_TESTS], [test "$enable_tests" = yes]) -AM_CONDITIONAL([COND_MMX], [test "$enable_mmx" = yes]) -AM_CONDITIONAL([COND_SSE], [test "$enable_sse" = yes]) -AM_CONDITIONAL([COND_SSE2], [test "$enable_sse2" = yes]) -AM_CONDITIONAL([COND_SSE3], [test "$enable_sse3" = yes]) -AM_CONDITIONAL([COND_SSSE3], [test "$enable_ssse3" = yes]) -AM_CONDITIONAL([COND_SSE4_1], [test "$enable_sse4_1" = yes]) -AM_CONDITIONAL([COND_SSE4_2], [test "$enable_sse4_2" = yes]) -AM_CONDITIONAL([COND_SSE4A], [test "$enable_sse4a" = yes]) -AM_CONDITIONAL([COND_SSE5], [test "$enable_sse5" = yes]) -AM_CONDITIONAL([COND_AVX], [test "$enable_avx" = yes]) -AM_CONDITIONAL([COND_AVX2], [test "$enable_avx2" = yes]) -AM_CONDITIONAL([COND_NEON], [test "$enable_neon" = yes]) - if test "$enable_builtin_tiff" = "yes" ; then abs_tiffdir="`cd $srcdir/../tiff-4.0.2/ && pwd`" save_CFLAGS=$CFLAGS @@ -553,9 +532,7 @@ if test "$enable_builtin_tiff" = "yes" ; then AC_DEFINE([HAVE_LIBTIFF], [1], [Define to 1 if you have the `tiff' library (-ltiff).]) else AC_CHECK_HEADERS([tiffio.h]) - AC_CHECK_HEADERS([tif_dir.h], [], [], [#include -]) - AC_CHECK_LIB([tiff], [TIFFOpen], [TIFF_LIBS="-ltiff"], AC_MSG_ERROR("Cannot build without libtiff (does your system require a libtiff-devel package?)"), -lm) + AC_CHECK_LIB([tiff], [TIFFOpen], , AC_MSG_ERROR("Cannot build without libtiff (does your system require a libtiff-devel package?)"), -lm) fi AC_CHECK_LIB([tiff], [TIFFCreateCustomDirectory], [ @@ -574,6 +551,45 @@ LIBS="$LIBS $TIFF_LIBS $JPEG_LIBS" TESTLIBS="$SIMLIBS $TESTLIBS" +if test "$enable_t43" = "yes" ; then + AC_DEFINE([SPANDSP_SUPPORT_T43], [1], [Support T.43 JBIG gray and colour compression]) + SPANDSP_SUPPORT_T43="#define SPANDSP_SUPPORT_T43 1" +else + SPANDSP_SUPPORT_T43="#undef SPANDSP_SUPPORT_T43" +fi + +if test "$enable_v32bis" = "yes" ; then + AC_DEFINE([SPANDSP_SUPPORT_V32BIS], [1], [Support the V.32bis modem]) + SPANDSP_SUPPORT_V32BIS="#define SPANDSP_SUPPORT_V32BIS 1" +else + SPANDSP_SUPPORT_V32BIS="#undef SPANDSP_SUPPORT_V32BIS" +fi + +if test "$enable_v34" = "yes" ; then + AC_DEFINE([SPANDSP_SUPPORT_V34], [1], [Support the V.34 FAX modem]) + SPANDSP_SUPPORT_V34="#define SPANDSP_SUPPORT_V34 1" +else + SPANDSP_SUPPORT_V34="#undef SPANDSP_SUPPORT_V34" +fi + +AM_CONDITIONAL([COND_DOC], [test "$enable_doc" = yes]) +AM_CONDITIONAL([COND_TESTS], [test "$enable_tests" = yes]) +AM_CONDITIONAL([COND_MMX], [test "$enable_mmx" = yes]) +AM_CONDITIONAL([COND_SSE], [test "$enable_sse" = yes]) +AM_CONDITIONAL([COND_SSE2], [test "$enable_sse2" = yes]) +AM_CONDITIONAL([COND_SSE3], [test "$enable_sse3" = yes]) +AM_CONDITIONAL([COND_SSSE3], [test "$enable_ssse3" = yes]) +AM_CONDITIONAL([COND_SSE4_1], [test "$enable_sse4_1" = yes]) +AM_CONDITIONAL([COND_SSE4_2], [test "$enable_sse4_2" = yes]) +AM_CONDITIONAL([COND_SSE4A], [test "$enable_sse4a" = yes]) +AM_CONDITIONAL([COND_SSE5], [test "$enable_sse5" = yes]) +AM_CONDITIONAL([COND_AVX], [test "$enable_avx" = yes]) +AM_CONDITIONAL([COND_AVX2], [test "$enable_avx2" = yes]) +AM_CONDITIONAL([COND_NEON], [test "$enable_neon" = yes]) + +AM_CONDITIONAL([COND_V32BIS], [test yes = xyes]) +AM_CONDITIONAL([COND_V34], [test yes = xyes]) + AC_SUBST(SPANDSP_LT_CURRENT) AC_SUBST(SPANDSP_LT_REVISION) AC_SUBST(SPANDSP_LT_AGE) @@ -586,7 +602,6 @@ AC_SUBST(TESTLIBS) AC_SUBST(SPANDSP_USE_FIXED_POINT) AC_SUBST(SPANDSP_MISALIGNED_ACCESS_FAILS) AC_SUBST(SPANDSP_USE_EXPORT_CAPABILITY) -AC_SUBST(SPANDSP_SUPPORT_T42) AC_SUBST(SPANDSP_SUPPORT_T43) AC_SUBST(SPANDSP_SUPPORT_V32BIS) AC_SUBST(SPANDSP_SUPPORT_V34) diff --git a/libs/spandsp/spandsp.spec b/libs/spandsp/spandsp.spec index 40ca9ddce3..d248ac71fb 100644 --- a/libs/spandsp/spandsp.spec +++ b/libs/spandsp/spandsp.spec @@ -2,12 +2,12 @@ Summary: A DSP library for telephony. Name: spandsp -Version: 0.0.7 +Version: 1.99.0 Release: 1 License: LGPLv2 and GPLv2 Group: System Environment/Libraries URL: http://www.soft-switch.org/spandsp -Source: http://www.soft-switch.org/downloads/spandsp/spandsp-0.0.7.tar.gz +Source: http://www.soft-switch.org/downloads/spandsp/spandsp-1.99.0.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: libtiff-devel%{?_isa} diff --git a/libs/spandsp/src/Makefile.am b/libs/spandsp/src/Makefile.am index a3b7a48ecd..9f60205f07 100644 --- a/libs/spandsp/src/Makefile.am +++ b/libs/spandsp/src/Makefile.am @@ -82,6 +82,16 @@ AM_CPPFLAGS = -I$(top_builddir) lib_LTLIBRARIES = libspandsp.la +if COND_V32BIS +V32BIS_SOURCES = v32bis.c +endif + +if COND_V34 +V34_SOURCES = v34rx.c \ + v34tx.c \ + v34_logging.c +endif + libspandsp_la_SOURCES = ademco_contactid.c \ adsi.c \ alloc.c \ @@ -173,7 +183,9 @@ libspandsp_la_SOURCES = ademco_contactid.c \ v42bis.c \ v8.c \ vector_float.c \ - vector_int.c + vector_int.c \ + $(V32BIS_SOURCES) \ + $(V34_SOURCES) libspandsp_la_LDFLAGS = -version-info @SPANDSP_LT_CURRENT@:@SPANDSP_LT_REVISION@:@SPANDSP_LT_AGE@ $(COMP_VENDOR_LDFLAGS) diff --git a/libs/spandsp/src/alloc.c b/libs/spandsp/src/alloc.c index 06600adb30..b79aa166e7 100644 --- a/libs/spandsp/src/alloc.c +++ b/libs/spandsp/src/alloc.c @@ -50,21 +50,25 @@ #include "spandsp/telephony.h" #include "spandsp/alloc.h" -#ifdef _MSC_VER +#if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable:4232) /* address of dllimport is not static, identity not guaranteed */ #endif #if defined(HAVE_ALIGNED_ALLOC) static span_aligned_alloc_t __span_aligned_alloc = aligned_alloc; +static span_aligned_free_t __span_aligned_free = free; #elif defined(HAVE_MEMALIGN) static span_aligned_alloc_t __span_aligned_alloc = memalign; -#elif defined(HAVE_POSIX_MEMALIGN) -static void *fake_posix_memalign(size_t alignment, size_t size); -static span_aligned_alloc_t __span_aligned_alloc = fake_posix_memalign; +static span_aligned_free_t __span_aligned_free = free; +#elif defined(__MSVC__) +static void *fake_aligned_alloc(size_t alignment, size_t size); +static span_aligned_alloc_t __span_aligned_alloc = fake_aligned_alloc; +static span_aligned_free_t __span_aligned_free = _aligned_free; #else static void *fake_aligned_alloc(size_t alignment, size_t size); static span_aligned_alloc_t __span_aligned_alloc = fake_aligned_alloc; +static span_aligned_free_t __span_aligned_free = free; #endif static span_alloc_t __span_alloc = malloc; static span_realloc_t __span_realloc = realloc; @@ -76,12 +80,19 @@ static span_free_t __span_free = free; #if defined(HAVE_ALIGNED_ALLOC) #elif defined(HAVE_MEMALIGN) +#elif defined(__MSVC__) +static void *fake_aligned_alloc(size_t alignment, size_t size) +{ + /* Make Microsoft's _aligned_malloc() look like the C11 aligned_alloc */ + return _aligned_malloc(size, alignment); +} +/*- End of function --------------------------------------------------------*/ #elif defined(HAVE_POSIX_MEMALIGN) -static void *fake_posix_memalign(size_t alignment, size_t size) +static void *fake_aligned_alloc(size_t alignment, size_t size) { void *ptr; - /* Make posix_memalign look like the more modern aligned_alloc */ + /* Make posix_memalign() look like the C11 aligned_alloc */ posix_memalign(&ptr, alignment, size); return ptr; } @@ -94,12 +105,6 @@ static void *fake_aligned_alloc(size_t alignment, size_t size) /*- End of function --------------------------------------------------------*/ #endif -SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size) -{ - return __span_aligned_alloc(alignment, size); -} -/*- End of function --------------------------------------------------------*/ - SPAN_DECLARE(void *) span_alloc(size_t size) { return __span_alloc(size); @@ -118,11 +123,28 @@ SPAN_DECLARE(void) span_free(void *ptr) } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc, - span_alloc_t custom_alloc, - span_realloc_t custom_realloc, - span_free_t custom_free) +SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size) { + return __span_aligned_alloc(alignment, size); +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(void) span_aligned_free(void *ptr) +{ + __span_aligned_free(ptr); +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) span_mem_allocators(span_alloc_t custom_alloc, + span_realloc_t custom_realloc, + span_free_t custom_free, + span_aligned_alloc_t custom_aligned_alloc, + span_aligned_free_t custom_aligned_free) +{ + __span_alloc = (custom_alloc) ? custom_alloc : malloc; + __span_realloc = (custom_realloc) ? custom_realloc : realloc; + __span_free = (custom_free) ? custom_free : free; + __span_aligned_alloc = (custom_aligned_alloc) ? custom_aligned_alloc @@ -131,14 +153,18 @@ SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc, aligned_alloc; #elif defined(HAVE_MEMALIGN) memalign; -#elif defined(HAVE_POSIX_MEMALIGN) - fake_posix_memalign; #else fake_aligned_alloc; #endif - __span_alloc = (custom_alloc) ? custom_alloc : malloc; - __span_realloc = (custom_realloc) ? custom_realloc : realloc; - __span_free = (custom_free) ? custom_free : free; + __span_aligned_free = (custom_aligned_free) + ? + custom_aligned_free + : +#if defined(__MSVC__) + _aligned_free; +#else + free; +#endif return 0; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/fax.c b/libs/spandsp/src/fax.c index a220c4f818..3a08d49218 100644 --- a/libs/spandsp/src/fax.c +++ b/libs/spandsp/src/fax.c @@ -84,9 +84,7 @@ #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" #include "spandsp/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" -#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" @@ -117,9 +115,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" -#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/image_translate.h" diff --git a/libs/spandsp/src/fax_modems.c b/libs/spandsp/src/fax_modems.c index 9f6cc4ba4c..413a464330 100644 --- a/libs/spandsp/src/fax_modems.c +++ b/libs/spandsp/src/fax_modems.c @@ -56,6 +56,7 @@ #include "spandsp/alloc.h" #include "spandsp/logging.h" #include "spandsp/bit_operations.h" +#include "spandsp/bitstream.h" #include "spandsp/dc_restore.h" #include "spandsp/queue.h" #include "spandsp/power_meter.h" @@ -73,14 +74,21 @@ #include "spandsp/v27ter_rx.h" #include "spandsp/v17tx.h" #include "spandsp/v17rx.h" +#if defined(SPANDSP_SUPPORT_V34) +#include "spandsp/v34.h" +#endif #include "spandsp/super_tone_rx.h" #include "spandsp/modem_connect_tones.h" #include "spandsp/fax_modems.h" #include "spandsp/private/logging.h" +#include "spandsp/private/bitstream.h" #include "spandsp/private/silence_gen.h" #include "spandsp/private/power_meter.h" #include "spandsp/private/fsk.h" +#if defined(SPANDSP_SUPPORT_V34) +#include "spandsp/private/v34.h" +#endif #include "spandsp/private/v17tx.h" #include "spandsp/private/v17rx.h" #include "spandsp/private/v27ter_tx.h" diff --git a/libs/spandsp/src/image_translate.c b/libs/spandsp/src/image_translate.c index 4c6a5affb8..1768b92138 100644 --- a/libs/spandsp/src/image_translate.c +++ b/libs/spandsp/src/image_translate.c @@ -67,9 +67,7 @@ #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" #include "spandsp/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" -#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" #include "spandsp/image_translate.h" @@ -78,9 +76,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" -#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/image_translate.h" diff --git a/libs/spandsp/src/libspandsp.2010.vcxproj b/libs/spandsp/src/libspandsp.2010.vcxproj index 8bb87b58c6..02d6ca77e0 100644 --- a/libs/spandsp/src/libspandsp.2010.vcxproj +++ b/libs/spandsp/src/libspandsp.2010.vcxproj @@ -211,6 +211,7 @@ + @@ -294,6 +295,7 @@ + @@ -305,6 +307,7 @@ + @@ -438,6 +441,10 @@ {329a6fa0-0fcc-4435-a950-e670aefa9838} false + + {eddb8ab9-c53e-44c0-a620-0e86c2cbd5d5} + false + diff --git a/libs/spandsp/src/libspandsp.2010.vcxproj.filters b/libs/spandsp/src/libspandsp.2010.vcxproj.filters index cc34e6c278..dea495c328 100644 --- a/libs/spandsp/src/libspandsp.2010.vcxproj.filters +++ b/libs/spandsp/src/libspandsp.2010.vcxproj.filters @@ -286,6 +286,9 @@ Source Files + + Source Files + @@ -725,6 +728,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/libs/spandsp/src/libspandsp.2012.vcxproj b/libs/spandsp/src/libspandsp.2012.vcxproj index dd99dbc2d9..a73a1b3c88 100644 --- a/libs/spandsp/src/libspandsp.2012.vcxproj +++ b/libs/spandsp/src/libspandsp.2012.vcxproj @@ -215,6 +215,7 @@ + @@ -298,6 +299,7 @@ + @@ -309,6 +311,7 @@ + @@ -442,6 +445,10 @@ {329a6fa0-0fcc-4435-a950-e670aefa9838} false + + {eddb8ab9-c53e-44c0-a620-0e86c2cbd5d5} + false + diff --git a/libs/spandsp/src/libspandsp.2012.vcxproj.filters b/libs/spandsp/src/libspandsp.2012.vcxproj.filters index cc34e6c278..dea495c328 100644 --- a/libs/spandsp/src/libspandsp.2012.vcxproj.filters +++ b/libs/spandsp/src/libspandsp.2012.vcxproj.filters @@ -286,6 +286,9 @@ Source Files + + Source Files + @@ -725,6 +728,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/libs/spandsp/src/make_t43_gray_code_tables.c b/libs/spandsp/src/make_t43_gray_code_tables.c index 9e45b120ef..c44adc27bb 100644 --- a/libs/spandsp/src/make_t43_gray_code_tables.c +++ b/libs/spandsp/src/make_t43_gray_code_tables.c @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) int j; int gray; int new_gray; - int restore; + int restore = 0; printf("static const int16_t gray_code[4096] =\n{\n"); for (i = 0; i < 4096; i++) diff --git a/libs/spandsp/src/msvc/make_t43_gray_code_tables.2010.vcxproj b/libs/spandsp/src/msvc/make_t43_gray_code_tables.2010.vcxproj new file mode 100644 index 0000000000..1ff1b7ec00 --- /dev/null +++ b/libs/spandsp/src/msvc/make_t43_gray_code_tables.2010.vcxproj @@ -0,0 +1,65 @@ + + + + + All + Win32 + + + + make_t43_gray_code_tables + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5} + make_t43_gray_code_tables + Win32Proj + + + + Application + Unicode + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(PlatformName)\$(Configuration)\ + $(PlatformName)\make_t43_gray_code_tables\$(Configuration)\ + false + + + + $(IntDir)BuildLog $(ProjectName).htm + + + Disabled + .;.\spandsp;.\msvc;..\..\tiff-4.0.2\libtiff;.\generated;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;HAVE_CONFIG_H;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + $(IntDir)$(TargetName).pdb + Level3 + ProgramDatabase + + + true + Console + MachineX86 + + + "$(TargetPath)" >"$(ProjectDir)..\t43_gray_code_tables.h" + + + + + + + + + diff --git a/libs/spandsp/src/msvc/make_t43_gray_code_tables.2010.vcxproj.filters b/libs/spandsp/src/msvc/make_t43_gray_code_tables.2010.vcxproj.filters new file mode 100644 index 0000000000..8ab1316fdc --- /dev/null +++ b/libs/spandsp/src/msvc/make_t43_gray_code_tables.2010.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + diff --git a/libs/spandsp/src/msvc/make_t43_gray_code_tables.2012.vcxproj b/libs/spandsp/src/msvc/make_t43_gray_code_tables.2012.vcxproj new file mode 100644 index 0000000000..6673241fe6 --- /dev/null +++ b/libs/spandsp/src/msvc/make_t43_gray_code_tables.2012.vcxproj @@ -0,0 +1,66 @@ + + + + + All + Win32 + + + + make_t43_gray_code_tables + {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5} + make_t43_gray_code_tables + Win32Proj + + + + Application + Unicode + v110 + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(PlatformName)\$(Configuration)\ + $(PlatformName)\make_t43_gray_code_tables\$(Configuration)\ + false + + + + $(IntDir)BuildLog $(ProjectName).htm + + + Disabled + .;.\spandsp;.\msvc;..\..\tiff-4.0.2\libtiff;.\generated;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;HAVE_CONFIG_H;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + $(IntDir)$(TargetName).pdb + Level3 + ProgramDatabase + + + true + Console + MachineX86 + + + "$(TargetPath)" >"$(ProjectDir)..\t43_gray_code_tables.h" + + + + + + + + + diff --git a/libs/spandsp/src/msvc/make_t43_gray_code_tables.2012.vcxproj.filters b/libs/spandsp/src/msvc/make_t43_gray_code_tables.2012.vcxproj.filters new file mode 100644 index 0000000000..8ab1316fdc --- /dev/null +++ b/libs/spandsp/src/msvc/make_t43_gray_code_tables.2012.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + diff --git a/libs/spandsp/src/msvc/spandsp.h b/libs/spandsp/src/msvc/spandsp.h index ec0b629d27..b98aa66aa4 100644 --- a/libs/spandsp/src/msvc/spandsp.h +++ b/libs/spandsp/src/msvc/spandsp.h @@ -117,9 +117,7 @@ #include #include #include -#if defined(SPANDSP_SUPPORT_T43) #include -#endif #include #include #include diff --git a/libs/spandsp/src/spandsp.h.in b/libs/spandsp/src/spandsp.h.in index 6ed699f3b4..747f4a432f 100644 --- a/libs/spandsp/src/spandsp.h.in +++ b/libs/spandsp/src/spandsp.h.in @@ -33,7 +33,6 @@ @SPANDSP_USE_EXPORT_CAPABILITY@ -@SPANDSP_SUPPORT_T42@ @SPANDSP_SUPPORT_T43@ @SPANDSP_SUPPORT_V32BIS@ @SPANDSP_SUPPORT_V34@ @@ -93,21 +92,21 @@ #include #include #include -#include -#include #include #include #include #include -#if defined(SPANDSP_SUPPORT_V32BIS) -#include -#endif #include #include #include +#if defined(SPANDSP_SUPPORT_V32BIS) +#include +#endif #if defined(SPANDSP_SUPPORT_V34) #include #endif +#include +#include #include #include #include @@ -118,9 +117,7 @@ #include #include #include -#if defined(SPANDSP_SUPPORT_T43) #include -#endif #include #include #include diff --git a/libs/spandsp/src/spandsp/alloc.h b/libs/spandsp/src/spandsp/alloc.h index 6ad81aa9be..3bb691b05a 100644 --- a/libs/spandsp/src/spandsp/alloc.h +++ b/libs/spandsp/src/spandsp/alloc.h @@ -28,7 +28,17 @@ #if !defined(_SPANDSP_ALLOC_H_) #define _SPANDSP_ALLOC_H_ +/* Notes: + - Most platforms don't have an aligned realloc function, so we don't try to + support an aligned realloc on any platform. + - Some platforms use a special free function for memory which was allocated + by alligned allocation functions. We use a separate aligned_free function + on all platforms, for compatibility, even though it may simply reduce to + free(). + */ + typedef void *(*span_aligned_alloc_t)(size_t alignment, size_t size); +typedef void (*span_aligned_free_t)(void *ptr); typedef void *(*span_alloc_t)(size_t size); typedef void *(*span_realloc_t)(void *ptr, size_t size); typedef void (*span_free_t)(void *ptr); @@ -41,20 +51,24 @@ extern "C" /* Allocate size bytes allocated to ALIGNMENT bytes. */ SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size); +/* Free a block allocated by span_aligned_alloc, or span_aligned_realloc. */ +SPAN_DECLARE(void) span_aligned_free(void *ptr); + /* Allocate size bytes of memory. */ SPAN_DECLARE(void *) span_alloc(size_t size); /* Re-allocate the previously allocated block in ptr, making the new block size bytes long. */ SPAN_DECLARE(void *) span_realloc(void *ptr, size_t size); -/* Free a block allocated by span_alloc, span_aligned_alloc, or span_realloc. */ +/* Free a block allocated by span_alloc or span_realloc. */ SPAN_DECLARE(void) span_free(void *ptr); -SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc, - span_alloc_t custom_alloc, +SPAN_DECLARE(int) span_mem_allocators(span_alloc_t custom_alloc, span_realloc_t custom_realloc, - span_free_t custom_free); - + span_free_t custom_free, + span_aligned_alloc_t custom_aligned_alloc, + span_aligned_free_t custom_aligned_free); + #if defined(__cplusplus) } #endif diff --git a/libs/spandsp/src/spandsp/expose.h b/libs/spandsp/src/spandsp/expose.h index a6ca48e5a5..b65a21f1b9 100644 --- a/libs/spandsp/src/spandsp/expose.h +++ b/libs/spandsp/src/spandsp/expose.h @@ -73,6 +73,12 @@ #include #include #include +#if defined(SPANDSP_SUPPORT_V32BIS) +#include +#endif +#if defined(SPANDSP_SUPPORT_V34) +#include +#endif #include #include #include diff --git a/libs/spandsp/src/spandsp/private/t30.h b/libs/spandsp/src/spandsp/private/t30.h index 06b35b67a2..4fe2cc12b9 100644 --- a/libs/spandsp/src/spandsp/private/t30.h +++ b/libs/spandsp/src/spandsp/private/t30.h @@ -46,6 +46,9 @@ struct t30_state_s /*! \brief True if behaving as the calling party */ bool calling_party; + /*! \brief True if bad quality pages should be kept */ + bool keep_bad_pages; + /*! \brief Internet aware FAX mode bit mask. */ int iaf; /*! \brief A bit mask of the currently supported modem types. */ @@ -139,6 +142,15 @@ struct t30_state_s /*! \brief An opaque pointer passed to the transmitted HDLC frame handler. */ void *send_hdlc_user_data; + /*! \brief The document send handler. */ + t30_document_get_handler_t document_get_handler; + /*! \brief An opaque pointer passed to the document send handler. */ + void *document_get_user_data; + /*! \brief The document delivery handler. */ + t30_document_put_handler_t document_put_handler; + /*! \brief An opaque pointer passed to the document delivery handler. */ + void *document_put_user_data; + /*! \brief The DIS code for the minimum scan row time we require. This is usually 0ms, but if we are trying to simulate another type of FAX machine, we may need a non-zero value here. */ diff --git a/libs/spandsp/src/spandsp/private/t4_rx.h b/libs/spandsp/src/spandsp/private/t4_rx.h index 99a3e5ef55..3f89e1d38b 100644 --- a/libs/spandsp/src/spandsp/private/t4_rx.h +++ b/libs/spandsp/src/spandsp/private/t4_rx.h @@ -91,6 +91,13 @@ typedef struct const char *dcs; } t4_rx_metadata_t; +typedef struct +{ + uint8_t *buf; + int buf_len; + int buf_ptr; +} no_decoder_state_t; + /*! T.4 FAX decompression descriptor. This defines the working state for a single instance of a T.4 FAX decompression channel. @@ -114,15 +121,14 @@ struct t4_rx_state_s union { + no_decoder_state_t no_decoder; t4_t6_decode_state_t t4_t6; t85_decode_state_t t85; #if defined(SPANDSP_SUPPORT_T88) t88_decode_state_t t88; #endif t42_decode_state_t t42; -#if defined(SPANDSP_SUPPORT_T43) t43_decode_state_t t43; -#endif #if defined(SPANDSP_SUPPORT_T45) t45_decode_state_t t45; #endif @@ -132,11 +138,6 @@ struct t4_rx_state_s int current_decoder; - uint8_t *pre_encoded_buf; - int pre_encoded_len; - int pre_encoded_ptr; - int pre_encoded_bit; - /* Supporting information, like resolutions, which the backend may want. */ t4_rx_metadata_t metadata; diff --git a/libs/spandsp/src/spandsp/private/t4_tx.h b/libs/spandsp/src/spandsp/private/t4_tx.h index 5ff0d2ea27..009152d9e2 100644 --- a/libs/spandsp/src/spandsp/private/t4_tx.h +++ b/libs/spandsp/src/spandsp/private/t4_tx.h @@ -100,6 +100,14 @@ typedef struct int resolution_code; } t4_tx_metadata_t; +typedef struct +{ + uint8_t *buf; + int buf_len; + int buf_ptr; + int bit; +} no_encoder_state_t; + /*! T.4 FAX compression descriptor. This defines the working state for a single instance of a T.4 FAX compression channel. @@ -149,15 +157,14 @@ struct t4_tx_state_s union { + no_encoder_state_t no_encoder; t4_t6_encode_state_t t4_t6; t85_encode_state_t t85; #if defined(SPANDSP_SUPPORT_T88) t88_encode_state_t t88; #endif t42_encode_state_t t42; -#if defined(SPANDSP_SUPPORT_T43) t43_encode_state_t t43; -#endif #if defined(SPANDSP_SUPPORT_T45) t45_encode_state_t t45; #endif @@ -176,10 +183,7 @@ struct t4_tx_state_s int pack_row; int pack_bit_mask; - uint8_t *pre_encoded_buf; - int pre_encoded_len; - int pre_encoded_ptr; - int pre_encoded_bit; + no_encoder_state_t no_encoder; /*! \brief Supporting information, like resolutions, which the backend may want. */ t4_tx_metadata_t metadata; diff --git a/libs/spandsp/src/spandsp/t30.h b/libs/spandsp/src/spandsp/t30.h index e4d734a8e4..6d43383eed 100644 --- a/libs/spandsp/src/spandsp/t30.h +++ b/libs/spandsp/src/spandsp/t30.h @@ -223,6 +223,26 @@ typedef void (*t30_set_handler_t)(void *user_data, int type, int bit_rate, int s */ typedef void (*t30_send_hdlc_handler_t)(void *user_data, const uint8_t msg[], int len); +/*! + T.30 send document handler. + \brief T.30 send document handler. + \param user_data An opaque pointer. + \param msg The document chunk. + \param len The length of the chunk. + \return The actual length of the chunk. +*/ +typedef int (*t30_document_get_handler_t)(void *user_data, uint8_t msg[], int len); + +/*! + T.30 deliver document handler. + \brief T.30 deliver handler. + \param user_data An opaque pointer. + \param msg The document chunk. + \param len The length of the chunk. + \return The delivery status. +*/ +typedef int (*t30_document_put_handler_t)(void *user_data, const uint8_t msg[], int len); + /*! T.30 protocol completion codes, at phase E. */ diff --git a/libs/spandsp/src/spandsp/t30_api.h b/libs/spandsp/src/spandsp/t30_api.h index 1c9a6e51de..90cefc4f58 100644 --- a/libs/spandsp/src/spandsp/t30_api.h +++ b/libs/spandsp/src/spandsp/t30_api.h @@ -225,6 +225,12 @@ SPAN_DECLARE(const char *) t30_get_tx_password(t30_state_t *s); \return A pointer to the password. */ SPAN_DECLARE(const char *) t30_get_rx_password(t30_state_t *s); +/*! Set the save bad quality pages handling associated with a T.30 context. + \brief Set the save bad quality pages handling associated with a T.30 context. + \param s The T.30 context. + \param keep_bad_pages True to save bad quality pages. */ +SPAN_DECLARE(void) t30_set_keep_bad_quality_pages(t30_state_t *s, bool keep_bad_pages); + /*! Set the transmitted TSA (i.e. the one we will send to the far end) associated with a T.30 context. \brief Set the transmitted TSA associated with a T.30 context. @@ -543,6 +549,10 @@ SPAN_DECLARE(void) t30_set_document_handler(t30_state_t *s, t30_document_handler \param user_data An opaque pointer passed to the callback function. */ SPAN_DECLARE(void) t30_set_real_time_frame_handler(t30_state_t *s, t30_real_time_frame_handler_t handler, void *user_data); +SPAN_DECLARE(void) t30_set_document_get_handler(t30_state_t *s, t30_document_get_handler_t handler, void *user_data); + +SPAN_DECLARE(void) t30_set_document_put_handler(t30_state_t *s, t30_document_put_handler_t handler, void *user_data); + /*! Get a pointer to the logging context associated with a T.30 context. \brief Get a pointer to the logging context associated with a T.30 context. \param s The T.30 context. diff --git a/libs/spandsp/src/spandsp/t42.h b/libs/spandsp/src/spandsp/t42.h index 17c4758a7f..26c4b8e299 100644 --- a/libs/spandsp/src/spandsp/t42.h +++ b/libs/spandsp/src/spandsp/t42.h @@ -76,6 +76,8 @@ SPAN_DECLARE(void) set_lab_gamut2(lab_params_t *s, int L_P, int L_Q, int a_P, in SPAN_DECLARE(void) get_lab_gamut2(lab_params_t *s, int *L_P, int *L_Q, int *a_P, int *a_Q, int *b_P, int *b_Q); +SPAN_DECLARE(bool) t42_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len); + SPAN_DECLARE(void) t42_encode_set_options(t42_encode_state_t *s, uint32_t l0, int quality, int options); SPAN_DECLARE(int) t42_encode_set_image_width(t42_encode_state_t *s, uint32_t image_width); diff --git a/libs/spandsp/src/spandsp/t4_tx.h b/libs/spandsp/src/spandsp/t4_tx.h index 019e2e6cd5..2e019e9dc5 100644 --- a/libs/spandsp/src/spandsp/t4_tx.h +++ b/libs/spandsp/src/spandsp/t4_tx.h @@ -175,7 +175,8 @@ ImageLayer(34732) LONG */ /* Define the TIFF/FX tags to extend libtiff, when using a version of libtiff where this - stuff has not been merged. */ + stuff has not been merged. We only need to define these things for older versions of + libtiff. */ #if defined(SPANDSP_SUPPORT_TIFF_FX) && !defined(TIFFTAG_FAXPROFILE) #define TIFFTAG_INDEXED 346 #define TIFFTAG_GLOBALPARAMETERSIFD 400 diff --git a/libs/spandsp/src/spandsp/t85.h b/libs/spandsp/src/spandsp/t85.h index d229026197..c6d6f0b47a 100644 --- a/libs/spandsp/src/spandsp/t85.h +++ b/libs/spandsp/src/spandsp/t85.h @@ -64,6 +64,8 @@ extern "C" { #endif +SPAN_DECLARE(bool) t85_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len); + /*! \brief Check if we are at the end of the current document page. \param s The T.85 context. \return 0 for more data to come. SIG_STATUS_END_OF_DATA for no more data. */ diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index 110b5b2e5d..7defb47d15 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -71,9 +71,7 @@ #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" #include "spandsp/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" -#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" #include "spandsp/t30_fcf.h" @@ -87,9 +85,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" -#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/image_translate.h" @@ -789,9 +785,13 @@ static int get_partial_ecm_page(t30_state_t *s) /* These frames contain a frame sequence number within the partial page (one octet) followed by some image data. */ s->ecm_data[i][3] = (uint8_t) i; - if ((len = t4_tx_get(&s->t4.tx, &s->ecm_data[i][4], s->octets_per_ecm_frame)) < s->octets_per_ecm_frame) + if (s->document_get_handler) + len = s->document_get_handler(s->document_get_user_data, &s->ecm_data[i][4], s->octets_per_ecm_frame); + else + len = t4_tx_get(&s->t4.tx, &s->ecm_data[i][4], s->octets_per_ecm_frame); + if (len < s->octets_per_ecm_frame) { - /* The image is not big enough to fill the entire buffer */ + /* The document is not big enough to fill the entire buffer */ /* We need to pad to a full frame, as most receivers expect that. */ if (len > 0) { @@ -799,7 +799,7 @@ static int get_partial_ecm_page(t30_state_t *s) s->ecm_len[i++] = (int16_t) (s->octets_per_ecm_frame + 4); } s->ecm_frames = i; - span_log(&s->logging, SPAN_LOG_FLOW, "Partial page buffer contains %d frames (%d per frame)\n", i, s->octets_per_ecm_frame); + span_log(&s->logging, SPAN_LOG_FLOW, "Partial document buffer contains %d frames (%d per frame)\n", i, s->octets_per_ecm_frame); s->ecm_at_page_end = true; return i; } @@ -1498,19 +1498,15 @@ static int build_dcs(t30_state_t *s) set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1); use_bilevel = false; break; -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T43_MODE); if (image_type == T4_IMAGE_TYPE_COLOUR_8BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT) set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE); if (image_type == T4_IMAGE_TYPE_GRAY_12BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT) set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT); - //if (???????? & T4_COMPRESSION_NO_SUBSAMPLING)) - // set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING); set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1); use_bilevel = false; break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: use_bilevel = false; @@ -1788,25 +1784,12 @@ static int analyze_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len) s->mutual_colour_resolutions &= ~T4_RESOLUTION_300_300; } if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE)) - { - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED)) - s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_400; - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED)) - s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_SUPERFINE; - } + s->mutual_bilevel_resolutions &= ~(T4_RESOLUTION_200_400 | T4_RESOLUTION_R8_SUPERFINE); if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE)) { - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED)) - s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_200; - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED)) - s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_FINE; + s->mutual_bilevel_resolutions &= ~(T4_RESOLUTION_200_200 | T4_RESOLUTION_R8_FINE); s->mutual_colour_resolutions &= ~T4_RESOLUTION_200_200; } - else - { - //if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED)) - // s->mutual_colour_resolutions &= ~T4_RESOLUTION_200_200; - } if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED)) s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_100; /* Never suppress T4_RESOLUTION_R8_STANDARD */ @@ -2853,6 +2836,7 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len) int first_bad_frame; int first; int expected_len; + int res; if (len < 7) { @@ -2986,11 +2970,18 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len) if (s->rx_ecm_block_ok) { span_log(&s->logging, SPAN_LOG_FLOW, "Partial page OK - committing block %d, %d frames\n", s->ecm_block, s->ecm_frames); + /* Deliver the ECM data */ for (i = 0; i < s->ecm_frames; i++) { - if (t4_rx_put(&s->t4.rx, s->ecm_data[i], s->ecm_len[i])) + if (s->document_put_handler) + res = s->document_put_handler(s->document_put_user_data, s->ecm_data[i], s->ecm_len[i]); + else + res = t4_rx_put(&s->t4.rx, s->ecm_data[i], s->ecm_len[i]); + if (res != T4_DECODE_MORE_DATA) { /* This is the end of the document */ + if (res != T4_DECODE_OK) + span_log(&s->logging, SPAN_LOG_FLOW, "Document ended with status %d\n", res); break; } } @@ -3642,6 +3633,53 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int } /*- End of function --------------------------------------------------------*/ +static void assess_copy_quality(t30_state_t *s, uint8_t fcf) +{ + int quality; + + quality = copy_quality(s); + switch (quality) + { + case T30_COPY_QUALITY_PERFECT: + case T30_COPY_QUALITY_GOOD: + rx_end_page(s); + break; + case T30_COPY_QUALITY_POOR: + rx_end_page(s); + break; + case T30_COPY_QUALITY_BAD: + /* Some people want to keep even the bad pages */ + if (s->keep_bad_pages) + rx_end_page(s); + break; + } + + if (s->phase_d_handler) + s->phase_d_handler(s, s->phase_d_user_data, fcf); + if (fcf == T30_EOP) + terminate_operation_in_progress(s); + else + rx_start_page(s); + + switch (quality) + { + case T30_COPY_QUALITY_PERFECT: + case T30_COPY_QUALITY_GOOD: + set_state(s, T30_STATE_III_Q_MCF); + send_simple_frame(s, T30_MCF); + break; + case T30_COPY_QUALITY_POOR: + set_state(s, T30_STATE_III_Q_RTP); + send_simple_frame(s, T30_RTP); + break; + case T30_COPY_QUALITY_BAD: + set_state(s, T30_STATE_III_Q_RTN); + send_simple_frame(s, T30_RTN); + break; + } +} +/*- End of function --------------------------------------------------------*/ + static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int len) { uint8_t fcf; @@ -3657,33 +3695,7 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, case T30_MPS: s->next_rx_step = fcf; queue_phase(s, T30_PHASE_D_TX); - switch (copy_quality(s)) - { - case T30_COPY_QUALITY_PERFECT: - case T30_COPY_QUALITY_GOOD: - rx_end_page(s); - if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, fcf); - rx_start_page(s); - set_state(s, T30_STATE_III_Q_MCF); - send_simple_frame(s, T30_MCF); - break; - case T30_COPY_QUALITY_POOR: - rx_end_page(s); - if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, fcf); - rx_start_page(s); - set_state(s, T30_STATE_III_Q_RTP); - send_simple_frame(s, T30_RTP); - break; - case T30_COPY_QUALITY_BAD: - if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, fcf); - rx_start_page(s); - set_state(s, T30_STATE_III_Q_RTN); - send_simple_frame(s, T30_RTN); - break; - } + assess_copy_quality(s, fcf); break; case T30_PRI_EOM: if (s->remote_interrupts_allowed) @@ -3695,33 +3707,7 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, s->next_rx_step = fcf; /* Return to phase B */ queue_phase(s, T30_PHASE_B_TX); - switch (copy_quality(s)) - { - case T30_COPY_QUALITY_PERFECT: - case T30_COPY_QUALITY_GOOD: - rx_end_page(s); - if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, fcf); - rx_start_page(s); - set_state(s, T30_STATE_III_Q_MCF); - send_simple_frame(s, T30_MCF); - break; - case T30_COPY_QUALITY_POOR: - rx_end_page(s); - if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, fcf); - rx_start_page(s); - set_state(s, T30_STATE_III_Q_RTP); - send_simple_frame(s, T30_RTP); - break; - case T30_COPY_QUALITY_BAD: - if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, fcf); - rx_start_page(s); - set_state(s, T30_STATE_III_Q_RTN); - send_simple_frame(s, T30_RTN); - break; - } + assess_copy_quality(s, fcf); break; case T30_PRI_EOP: if (s->remote_interrupts_allowed) @@ -3733,37 +3719,7 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, s->end_of_procedure_detected = true; s->next_rx_step = fcf; queue_phase(s, T30_PHASE_D_TX); - switch (copy_quality(s)) - { - case T30_COPY_QUALITY_PERFECT: - case T30_COPY_QUALITY_GOOD: - rx_end_page(s); - if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, fcf); - terminate_operation_in_progress(s); - set_state(s, T30_STATE_III_Q_MCF); - send_simple_frame(s, T30_MCF); - break; - case T30_COPY_QUALITY_POOR: - rx_end_page(s); - if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, fcf); - terminate_operation_in_progress(s); - set_state(s, T30_STATE_III_Q_RTP); - send_simple_frame(s, T30_RTP); - break; - case T30_COPY_QUALITY_BAD: -#if 0 - /* Some people want to keep even the bad pages */ - if (s->keep_bad_pages) - rx_end_page(s); -#endif - if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, fcf); - set_state(s, T30_STATE_III_Q_RTN); - send_simple_frame(s, T30_RTN); - break; - } + assess_copy_quality(s, fcf); break; case T30_DCN: t30_set_status(s, T30_ERR_RX_DCNFAX); @@ -5827,6 +5783,7 @@ static void t30_non_ecm_rx_status(void *user_data, int status) SPAN_DECLARE_NONSTD(void) t30_non_ecm_put_bit(void *user_data, int bit) { t30_state_t *s; + int res; if (bit < 0) { @@ -5851,10 +5808,12 @@ SPAN_DECLARE_NONSTD(void) t30_non_ecm_put_bit(void *user_data, int bit) } break; case T30_STATE_F_DOC_NON_ECM: - /* Document transfer */ - if (t4_rx_put_bit(&s->t4.rx, bit) == T4_DECODE_OK) + /* Image transfer */ + if ((res = t4_rx_put_bit(&s->t4.rx, bit)) != T4_DECODE_MORE_DATA) { - /* That is the end of the document */ + /* This is the end of the image */ + if (res != T4_DECODE_OK) + span_log(&s->logging, SPAN_LOG_FLOW, "Page ended with status %d\n", res); set_state(s, T30_STATE_F_POST_DOC_NON_ECM); queue_phase(s, T30_PHASE_D_RX); timer_t2_start(s); @@ -5868,6 +5827,7 @@ SPAN_DECLARE(void) t30_non_ecm_put(void *user_data, const uint8_t buf[], int len { t30_state_t *s; int i; + int res; s = (t30_state_t *) user_data; switch (s->state) @@ -5891,10 +5851,12 @@ SPAN_DECLARE(void) t30_non_ecm_put(void *user_data, const uint8_t buf[], int len } break; case T30_STATE_F_DOC_NON_ECM: - /* Document transfer */ - if (t4_rx_put(&s->t4.rx, buf, len)) + /* Image transfer */ + if ((res = t4_rx_put(&s->t4.rx, buf, len)) != T4_DECODE_MORE_DATA) { - /* That is the end of the document */ + /* This is the end of the image */ + if (res != T4_DECODE_OK) + span_log(&s->logging, SPAN_LOG_FLOW, "Page ended with status %d\n", res); set_state(s, T30_STATE_F_POST_DOC_NON_ECM); queue_phase(s, T30_PHASE_D_RX); timer_t2_start(s); @@ -6706,8 +6668,8 @@ SPAN_DECLARE(t30_state_t *) t30_init(t30_state_t *s, | T4_SUPPORT_LENGTH_A4 | T4_SUPPORT_LENGTH_B4 | T4_SUPPORT_LENGTH_UNLIMITED; - /* Set the output encoding to something safe. For bi-level images ost things get - 1D and 2D encoding right. Quite a lot get other things wrong. */ + /* Set the output encoding to something safe. For bi-level images most things + get 1D and 2D encoding right. Quite a lot get other things wrong. */ s->supported_output_compressions = T4_COMPRESSION_T4_2D | T4_COMPRESSION_JPEG; s->local_min_scan_time_code = T30_MIN_SCAN_0MS; span_log_init(&s->logging, SPAN_LOG_NONE, NULL); diff --git a/libs/spandsp/src/t30_api.c b/libs/spandsp/src/t30_api.c index a0a78b3164..6d0bca3840 100644 --- a/libs/spandsp/src/t30_api.c +++ b/libs/spandsp/src/t30_api.c @@ -71,9 +71,7 @@ #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" #include "spandsp/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" -#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" #include "spandsp/t30_fcf.h" @@ -87,9 +85,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" -#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/image_translate.h" @@ -652,8 +648,36 @@ SPAN_DECLARE(int) t30_set_ecm_capability(t30_state_t *s, bool enabled) } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(void) t30_set_keep_bad_quality_pages(t30_state_t *s, bool keep_bad_pages) +{ + s->keep_bad_pages = keep_bad_pages; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(int) t30_set_supported_output_compressions(t30_state_t *s, int supported_compressions) { + /* Mask out the ones we actually support today. */ + supported_compressions &= T4_COMPRESSION_T4_1D + | T4_COMPRESSION_T4_2D + | T4_COMPRESSION_T6 + | T4_COMPRESSION_T85 + | T4_COMPRESSION_T85_L0 +#if defined(SPANDSP_SUPPORT_T88) + | T4_COMPRESSION_T88 +#endif + | T4_COMPRESSION_T42_T81 +#if defined(SPANDSP_SUPPORT_SYCC_T81) + | T4_COMPRESSION_SYCC_T81 +#endif +#if defined(SPANDSP_SUPPORT_T43) + | T4_COMPRESSION_T43 +#endif +#if defined(SPANDSP_SUPPORT_T45) + | T4_COMPRESSION_T45 +#endif + | T4_COMPRESSION_UNCOMPRESSED + | T4_COMPRESSION_JPEG + | 0; s->supported_output_compressions = supported_compressions; return 0; } @@ -841,6 +865,20 @@ SPAN_DECLARE(void) t30_set_real_time_frame_handler(t30_state_t *s, t30_real_time } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(void) t30_set_document_get_handler(t30_state_t *s, t30_document_get_handler_t handler, void *user_data) +{ + s->document_get_handler = handler; + s->document_get_user_data = user_data; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(void) t30_set_document_put_handler(t30_state_t *s, t30_document_put_handler_t handler, void *user_data) +{ + s->document_put_handler = handler; + s->document_put_user_data = user_data; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(logging_state_t *) t30_get_logging_state(t30_state_t *s) { return &s->logging; diff --git a/libs/spandsp/src/t30_logging.c b/libs/spandsp/src/t30_logging.c index ce1dc74664..a3dea97b2e 100644 --- a/libs/spandsp/src/t30_logging.c +++ b/libs/spandsp/src/t30_logging.c @@ -70,9 +70,7 @@ #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" #include "spandsp/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" -#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" #include "spandsp/t30_fcf.h" @@ -85,9 +83,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" -#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/image_translate.h" diff --git a/libs/spandsp/src/t38_gateway.c b/libs/spandsp/src/t38_gateway.c index 78346e3ecf..77225cc63f 100644 --- a/libs/spandsp/src/t38_gateway.c +++ b/libs/spandsp/src/t38_gateway.c @@ -84,9 +84,7 @@ #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" #include "spandsp/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" -#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" #include "spandsp/t30_fcf.h" @@ -115,9 +113,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" -#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/image_translate.h" diff --git a/libs/spandsp/src/t38_terminal.c b/libs/spandsp/src/t38_terminal.c index bf6a2a9de7..75d8842d9a 100644 --- a/libs/spandsp/src/t38_terminal.c +++ b/libs/spandsp/src/t38_terminal.c @@ -74,9 +74,7 @@ #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" #include "spandsp/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" -#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" #include "spandsp/t30_fcf.h" @@ -92,9 +90,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" -#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/image_translate.h" diff --git a/libs/spandsp/src/t42.c b/libs/spandsp/src/t42.c index 1469c389be..37c98e1d95 100644 --- a/libs/spandsp/src/t42.c +++ b/libs/spandsp/src/t42.c @@ -72,7 +72,7 @@ #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -/* The open_memstream() and fmemopen() in older versions of glibc seems quirky */ +/* The open_memstream() and fmemopen() in older versions of glibc seem quirky */ #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 12)) #undef OPEN_MEMSTREAM #endif @@ -230,6 +230,38 @@ static __inline__ int unpack_16(uint8_t *s, uint16_t value) } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(bool) t42_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len) +{ + int type; + int seg; + int pos; + + /* Search the image data for its width and length */ + *length = 0; + *width = 0; + + pos = 0; + if (pack_16(&data[pos]) != 0xFFD8) + return false; + pos += 2; + while (pos < len) + { + type = pack_16(&data[pos]); + pos += 2; + seg = pack_16(&data[pos]) - 2; + pos += 2; + if (type == 0xFFC0) + { + *length = pack_16(&data[pos + 1]); + *width = pack_16(&data[pos + 3]); + return true; + } + pos += seg; + } + return false; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(int) xyz_to_corrected_color_temp(float *temp, float xyz[3]) { float us; diff --git a/libs/spandsp/src/t43.c b/libs/spandsp/src/t43.c index 181226e757..ec7e67ea3a 100644 --- a/libs/spandsp/src/t43.c +++ b/libs/spandsp/src/t43.c @@ -865,7 +865,8 @@ SPAN_DECLARE(int) t43_decode_restart(t43_decode_state_t *s) { /* ITULAB */ /* Illuminant D50 */ - set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f); + //set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f); + set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f); set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, false); s->t85.min_bit_planes = 1; @@ -898,7 +899,8 @@ SPAN_DECLARE(t43_decode_state_t *) t43_decode_init(t43_decode_state_t *s, /* ITULAB */ /* Illuminant D50 */ - set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f); + //set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f); + set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f); set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, false); s->t85.min_bit_planes = 1; diff --git a/libs/spandsp/src/t4_rx.c b/libs/spandsp/src/t4_rx.c index 141a6529e9..69a98193a1 100644 --- a/libs/spandsp/src/t4_rx.c +++ b/libs/spandsp/src/t4_rx.c @@ -64,9 +64,7 @@ #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" #include "spandsp/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" -#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" #include "spandsp/version.h" @@ -75,9 +73,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" -#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/image_translate.h" @@ -94,8 +90,10 @@ typedef struct } packer_t; #if defined(SPANDSP_SUPPORT_TIFF_FX) +#if TIFFLIB_VERSION >= 20120615 extern TIFFFieldArray tiff_fx_field_array; #endif +#endif SPAN_DECLARE(const char *) t4_compression_to_str(int compression) { @@ -213,6 +211,8 @@ static int set_tiff_directory_info(t4_rx_state_t *s) int bits_per_sample; int samples_per_pixel; int photometric; + uint32_t width; + uint32_t length; t = &s->tiff; /* Prepare the directory entry fully before writing the image, or libtiff complains */ @@ -242,7 +242,6 @@ static int set_tiff_directory_info(t4_rx_state_t *s) output_compression = COMPRESSION_T88; break; #endif -#if defined(SPANDSP_SUPPORT_T42) case T4_COMPRESSION_JPEG: output_compression = COMPRESSION_JPEG; bits_per_sample = 8; @@ -274,18 +273,23 @@ static int set_tiff_directory_info(t4_rx_state_t *s) case T4_COMPRESSION_SYCC_T81: output_compression = COMPRESSION_JPEG; bits_per_sample = 8; - samples_per_pixel = 3; - photometric = PHOTOMETRIC_YCBCR; + if (t->image_type == T4_IMAGE_TYPE_COLOUR_8BIT) + { + samples_per_pixel = 3; + photometric = PHOTOMETRIC_YCBCR; + } + else + { + samples_per_pixel = 1; + photometric = PHOTOMETRIC_MINISBLACK; + } break; -#endif -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: output_compression = COMPRESSION_T43; bits_per_sample = 8; samples_per_pixel = 3; photometric = PHOTOMETRIC_ITULAB; break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: output_compression = COMPRESSION_T45; @@ -313,11 +317,9 @@ static int set_tiff_directory_info(t4_rx_state_t *s) case COMPRESSION_JPEG: TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); break; -#if defined(SPANDSP_SUPPORT_T43) case COMPRESSION_T43: TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); break; -#endif } TIFFSetField(t->tiff_file, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, bits_per_sample); @@ -399,7 +401,21 @@ static int set_tiff_directory_info(t4_rx_state_t *s) switch (s->current_decoder) { case 0: - s->metadata.image_length = 1024; + switch (t->compression) + { + case T4_COMPRESSION_T42_T81: + case T4_COMPRESSION_SYCC_T81: + t42_analyse_header(&width, &length, s->decoder.no_decoder.buf, s->decoder.no_decoder.buf_ptr); + s->metadata.image_width = width; + s->metadata.image_length = length; + break; + case T4_COMPRESSION_T85: + case T4_COMPRESSION_T85_L0: + t85_analyse_header(&width, &length, s->decoder.no_decoder.buf, s->decoder.no_decoder.buf_ptr); + s->metadata.image_width = width; + s->metadata.image_length = length; + break; + } break; case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6: if ((s->metadata.compression & (T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D))) @@ -432,11 +448,9 @@ static int set_tiff_directory_info(t4_rx_state_t *s) case T4_COMPRESSION_T42_T81: s->metadata.image_length = t42_decode_get_image_length(&s->decoder.t42); break; -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: s->metadata.image_length = t43_decode_get_image_length(&s->decoder.t43); break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: s->metadata.image_length = t45_decode_get_image_length(&s->decoder.t45); @@ -555,7 +569,6 @@ static int write_tiff_t85_image(t4_rx_state_t *s) } /*- End of function --------------------------------------------------------*/ -#if defined(SPANDSP_SUPPORT_T43) static int write_tiff_t43_image(t4_rx_state_t *s) { uint8_t *buf; @@ -597,7 +610,6 @@ static int write_tiff_t43_image(t4_rx_state_t *s) return 0; } /*- End of function --------------------------------------------------------*/ -#endif static int write_tiff_image(t4_rx_state_t *s) { @@ -607,7 +619,7 @@ static int write_tiff_image(t4_rx_state_t *s) #endif t = &s->tiff; - if (s->pre_encoded_ptr <= 0 && (t->image_buffer == NULL || t->image_size <= 0)) + if (s->decoder.no_decoder.buf_ptr <= 0 && (t->image_buffer == NULL || t->image_size <= 0)) return -1; /* Set up the TIFF directory info... */ set_tiff_directory_info(s); @@ -616,9 +628,9 @@ static int write_tiff_image(t4_rx_state_t *s) //if (!TIFFCheckpointDirectory(t->tiff_file)) // span_log(&s->logging, SPAN_LOG_WARNING, "%s: Failed to checkpoint directory for page %d.\n", t->file, s->current_page); /* ...and write out the image... */ - if (s->pre_encoded_ptr > 0) + if (s->current_decoder == 0) { - if (TIFFWriteRawStrip(s->tiff.tiff_file, 0, s->pre_encoded_buf, s->pre_encoded_ptr) < 0) + if (TIFFWriteRawStrip(s->tiff.tiff_file, 0, s->decoder.no_decoder.buf, s->decoder.no_decoder.buf_ptr) < 0) span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", s->tiff.file); } else @@ -638,13 +650,11 @@ static int write_tiff_image(t4_rx_state_t *s) return -1; break; #endif -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: /* We need to perform this compression here, as libtiff does not understand it. */ if (write_tiff_t43_image(s) < 0) return -1; break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: /* We need to perform this compression here, as libtiff does not understand it. */ @@ -752,30 +762,57 @@ SPAN_DECLARE(int) t4_rx_put_bit(t4_rx_state_t *s, int bit) } /*- End of function --------------------------------------------------------*/ +static void pre_encoded_restart(no_decoder_state_t *s) +{ + s->buf_ptr = 0; +} +/*- End of function --------------------------------------------------------*/ + +static void pre_encoded_init(no_decoder_state_t *s) +{ + s->buf = NULL; + s->buf_len = 0; + s->buf_ptr = 0; +} +/*- End of function --------------------------------------------------------*/ + +static int pre_encoded_release(no_decoder_state_t *s) +{ + if (s->buf) + span_free(s->buf); + return 0; +} +/*- End of function --------------------------------------------------------*/ + +static int pre_encoded_put(no_decoder_state_t *s, const uint8_t data[], size_t len) +{ + uint8_t *buf; + + if (s->buf_len < s->buf_ptr + len) + { + s->buf_len += 65536; + if ((buf = span_realloc(s->buf, s->buf_len)) == NULL) + { + if (s->buf) + { + span_free(s->buf); + s->buf = NULL; + s->buf_len = 0; + } + return -1; + } + s->buf = buf; + } + memcpy(&s->buf[s->buf_ptr], data, len); + s->buf_ptr += len; + return T4_DECODE_MORE_DATA; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(int) t4_rx_put(t4_rx_state_t *s, const uint8_t buf[], size_t len) { - uint8_t *buf2; - s->line_image_size += 8*len; - if (s->pre_encoded_len > 0) - { - if (s->pre_encoded_len < s->pre_encoded_ptr + 65536) - { - s->pre_encoded_len += 65536; - if ((buf2 = span_realloc(s->pre_encoded_buf, s->pre_encoded_len)) == NULL) - { - if (s->pre_encoded_buf) - span_free(s->pre_encoded_buf); - return -1; - } - s->pre_encoded_buf = buf2; - } - memcpy(&s->pre_encoded_buf[s->pre_encoded_ptr], buf, len); - s->pre_encoded_ptr += len; - return T4_DECODE_MORE_DATA; - } - if (s->image_put_handler) return s->image_put_handler((void *) &s->decoder, buf, len); @@ -825,13 +862,26 @@ SPAN_DECLARE(void) t4_rx_set_model(t4_rx_state_t *s, const char *model) } /*- End of function --------------------------------------------------------*/ -static void select_tiff_compression(t4_rx_state_t *s, int output_image_type) +static bool select_tiff_compression(t4_rx_state_t *s, int output_image_type) { + s->tiff.image_type = output_image_type; + /* The only compression schemes where we can really avoid decoding and + recoding the images are those where the width an length of the image + can be readily extracted from the image data (e.g. from its header) */ + if ((s->metadata.compression & (s->supported_tiff_compressions & (T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0 | T4_COMPRESSION_T42_T81 | T4_COMPRESSION_SYCC_T81)))) + { + span_log(&s->logging, SPAN_LOG_FLOW, "Image can be written without recoding\n"); + s->tiff.compression = s->metadata.compression; + return false; + } + if (output_image_type == T4_IMAGE_TYPE_BILEVEL) { /* Only provide for one form of coding throughout the file, even though the coding on the wire could change between pages. */ - if ((s->supported_tiff_compressions & T4_COMPRESSION_T85)) + if ((s->supported_tiff_compressions & T4_COMPRESSION_T88)) + s->tiff.compression = T4_COMPRESSION_T88; + else if ((s->supported_tiff_compressions & T4_COMPRESSION_T85)) s->tiff.compression = T4_COMPRESSION_T85; else if ((s->supported_tiff_compressions & T4_COMPRESSION_T6)) s->tiff.compression = T4_COMPRESSION_T6; @@ -848,22 +898,44 @@ static void select_tiff_compression(t4_rx_state_t *s, int output_image_type) s->tiff.compression = T4_COMPRESSION_T42_T81; else if ((s->supported_tiff_compressions & T4_COMPRESSION_T43)) s->tiff.compression = T4_COMPRESSION_T43; + else if ((s->supported_tiff_compressions & T4_COMPRESSION_T45)) + s->tiff.compression = T4_COMPRESSION_T45; else if ((s->supported_tiff_compressions & T4_COMPRESSION_UNCOMPRESSED)) s->tiff.compression = T4_COMPRESSION_UNCOMPRESSED; } - s->tiff.image_type = output_image_type; + return true; +} +/*- End of function --------------------------------------------------------*/ + +static int release_current_decoder(t4_rx_state_t *s) +{ + switch (s->current_decoder) + { + case 0: + return pre_encoded_release(&s->decoder.no_decoder); + case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6: + return t4_t6_decode_release(&s->decoder.t4_t6); + case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0: + return t85_decode_release(&s->decoder.t85); +#if defined(SPANDSP_SUPPORT_T88) + case T4_COMPRESSION_T88: + return t88_decode_release(&s->decoder.t88); +#endif + case T4_COMPRESSION_T42_T81: + return t42_decode_release(&s->decoder.t42); + case T4_COMPRESSION_T43: + return t43_decode_release(&s->decoder.t43); +#if defined(SPANDSP_SUPPORT_T45) + case T4_COMPRESSION_T45: + return t45_decode_release(&s->decoder.t45); +#endif + } + return 0; } /*- End of function --------------------------------------------------------*/ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) { -#if 0 - output_image_type = T4_IMAGE_TYPE_BILEVEL; - s->metadata.compression = compression; - select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL); - s->current_decoder = 0; - return 0; -#else switch (compression) { case T4_COMPRESSION_T4_1D: @@ -876,12 +948,18 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) case T4_COMPRESSION_T6: break; default: + release_current_decoder(s); t4_t6_decode_init(&s->decoder.t4_t6, compression, s->metadata.image_width, s->row_handler, s->row_handler_user_data); s->current_decoder = T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6; break; } s->metadata.compression = compression; - select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL); + if (!select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL)) + { + release_current_decoder(s); + s->current_decoder = 0; + pre_encoded_init(&s->decoder.no_decoder); + } return t4_t6_decode_set_encoding(&s->decoder.t4_t6, compression); case T4_COMPRESSION_T85: case T4_COMPRESSION_T85_L0: @@ -891,6 +969,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) case T4_COMPRESSION_T85_L0: break; default: + release_current_decoder(s); t85_decode_init(&s->decoder.t85, s->row_handler, s->row_handler_user_data); s->current_decoder = T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0; /* Constrain received images to the maximum width of any FAX. This will @@ -900,7 +979,12 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) break; } s->metadata.compression = compression; - select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL); + if (!select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL)) + { + release_current_decoder(s); + s->current_decoder = 0; + pre_encoded_init(&s->decoder.no_decoder); + } return 0; #if defined(SPANDSP_SUPPORT_T88) case T4_COMPRESSION_T88: @@ -909,12 +993,18 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) case T4_COMPRESSION_T88: break; default: + release_current_decoder(s); t88_decode_init(&s->decoder.t88, s->row_handler, s->row_handler_user_data); s->current_decoder = T4_COMPRESSION_T88; break; } s->metadata.compression = compression; - select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL); + if (!select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL)) + { + release_current_decoder(s); + s->current_decoder = 0; + pre_encoded_init(&s->decoder.no_decoder); + } return 0; #endif case T4_COMPRESSION_T42_T81: @@ -925,6 +1015,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) case T4_COMPRESSION_SYCC_T81: break; default: + release_current_decoder(s); t42_decode_init(&s->decoder.t42, s->row_handler, s->row_handler_user_data); s->current_decoder = T4_COMPRESSION_T42_T81; /* Constrain received images to the maximum width of any FAX. This will @@ -934,15 +1025,20 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) break; } s->metadata.compression = compression; - select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT); + if (!select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT)) + { + release_current_decoder(s); + s->current_decoder = 0; + pre_encoded_init(&s->decoder.no_decoder); + } return 0; -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: switch (s->metadata.compression) { case T4_COMPRESSION_T43: break; default: + release_current_decoder(s); t43_decode_init(&s->decoder.t43, s->row_handler, s->row_handler_user_data); s->current_decoder = T4_COMPRESSION_T43; /* Constrain received images to the maximum width of any FAX. This will @@ -952,9 +1048,13 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) break; } s->metadata.compression = compression; - select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT); + if (!select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT)) + { + release_current_decoder(s); + s->current_decoder = 0; + pre_encoded_init(&s->decoder.no_decoder); + } return 0; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: switch (s->metadata.compression) @@ -962,18 +1062,23 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) case T4_COMPRESSION_T45: break; default: + release_current_decoder(s); t45_decode_init(&s->decoder.t45, s->row_handler, s->row_handler_user_data); s->current_decoder = T4_COMPRESSION_T45; break; } s->metadata.compression = compression; - select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT); + if (!select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT)) + { + release_current_decoder(s); + s->current_decoder = 0; + pre_encoded_init(&s->decoder.no_decoder); + } return 0; #endif } return -1; -#endif } /*- End of function --------------------------------------------------------*/ @@ -999,10 +1104,8 @@ SPAN_DECLARE(int) t4_rx_set_row_write_handler(t4_rx_state_t *s, t4_row_write_han #endif case T4_COMPRESSION_T42_T81: return t42_decode_set_row_write_handler(&s->decoder.t42, handler, user_data); -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: return t43_decode_set_row_write_handler(&s->decoder.t43, handler, user_data); -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: return t45_decode_set_row_write_handler(&s->decoder.t45, handler, user_data); @@ -1026,6 +1129,15 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t t->compression = s->metadata.compression; switch (s->current_decoder) { + case 0: + t->type = 0; + t->width = s->metadata.image_width; + t->length = s->metadata.image_length; + t->image_type = 0; + t->image_width = t->width; + t->image_length = t->length; + t->line_image_size = s->line_image_size; + break; case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6: t->type = T4_IMAGE_TYPE_BILEVEL; t->width = t4_t6_decode_get_image_width(&s->decoder.t4_t6); @@ -1059,7 +1171,6 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t t->image_length = t->length; t->line_image_size = t42_decode_get_compressed_image_size(&s->decoder.t42)/8; break; -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: t->type = T4_IMAGE_TYPE_COLOUR_8BIT; t->width = t43_decode_get_image_width(&s->decoder.t43); @@ -1069,7 +1180,6 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t t->image_length = t->length; t->line_image_size = t43_decode_get_compressed_image_size(&s->decoder.t43)/8; break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: break; @@ -1085,9 +1195,8 @@ SPAN_DECLARE(int) t4_rx_start_page(t4_rx_state_t *s) switch (s->current_decoder) { case 0: - s->pre_encoded_ptr = 0; - s->pre_encoded_len = 0; - s->image_put_handler = NULL; + pre_encoded_restart(&s->decoder.no_decoder); + s->image_put_handler = (t4_image_put_handler_t) pre_encoded_put; break; case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6: t4_t6_decode_restart(&s->decoder.t4_t6, s->metadata.image_width); @@ -1107,12 +1216,10 @@ SPAN_DECLARE(int) t4_rx_start_page(t4_rx_state_t *s) t42_decode_restart(&s->decoder.t42); s->image_put_handler = (t4_image_put_handler_t) t42_decode_put; break; -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: t43_decode_restart(&s->decoder.t43); s->image_put_handler = (t4_image_put_handler_t) t43_decode_put; break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: t45_decode_restart(&s->decoder.t45); @@ -1163,7 +1270,7 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s) switch (s->current_decoder) { case 0: - length = s->pre_encoded_ptr; + length = s->decoder.no_decoder.buf_ptr; break; case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6: length = t4_t6_decode_get_image_length(&s->decoder.t4_t6); @@ -1179,15 +1286,13 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s) case T4_COMPRESSION_T42_T81: length = t42_decode_get_image_length(&s->decoder.t42); if (s->decoder.t42.samples_per_pixel == 3) - select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT); + s->tiff.image_type = T4_IMAGE_TYPE_COLOUR_8BIT; else - select_tiff_compression(s, T4_IMAGE_TYPE_GRAY_8BIT); + s->tiff.image_type = T4_IMAGE_TYPE_GRAY_8BIT; break; -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: length = t43_decode_get_image_length(&s->decoder.t43); break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: length = t45_decode_get_image_length(&s->decoder.t45); @@ -1203,7 +1308,6 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s) if (write_tiff_image(s) == 0) s->current_page++; s->tiff.image_size = 0; - s->pre_encoded_ptr = 0; } else { @@ -1240,6 +1344,15 @@ SPAN_DECLARE(t4_rx_state_t *) t4_rx_init(t4_rx_state_t *s, const char *file, int span_log(&s->logging, SPAN_LOG_FLOW, "Start rx document\n"); s->supported_tiff_compressions = supported_output_compressions; +#if !defined(SPANDSP_SUPPORT_T88) + s->supported_tiff_compressions &= ~T4_COMPRESSION_T88; +#endif +#if !defined(SPANDSP_SUPPORT_T43) + s->supported_tiff_compressions &= ~T4_COMPRESSION_T43; +#endif +#if !defined(SPANDSP_SUPPORT_T45) + s->supported_tiff_compressions &= ~T4_COMPRESSION_T45; +#endif /* Set some default values */ s->metadata.x_resolution = T4_X_RESOLUTION_R8; @@ -1272,27 +1385,7 @@ SPAN_DECLARE(int) t4_rx_release(t4_rx_state_t *s) { if (s->tiff.file) tiff_rx_release(s); - switch (s->current_decoder) - { - case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6: - return t4_t6_decode_release(&s->decoder.t4_t6); - case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0: - return t85_decode_release(&s->decoder.t85); -#if defined(SPANDSP_SUPPORT_T88) - case T4_COMPRESSION_T88: - return t88_decode_release(&s->decoder.t88); -#endif - case T4_COMPRESSION_T42_T81: - return t42_decode_release(&s->decoder.t42); -#if defined(SPANDSP_SUPPORT_T43) - case T4_COMPRESSION_T43: - return t43_decode_release(&s->decoder.t43); -#endif -#if defined(SPANDSP_SUPPORT_T45) - case T4_COMPRESSION_T45: - return t45_decode_release(&s->decoder.t45); -#endif - } + release_current_decoder(s); return -1; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/t4_t6_decode.c b/libs/spandsp/src/t4_t6_decode.c index 4daf7e65c7..b163277e22 100644 --- a/libs/spandsp/src/t4_t6_decode.c +++ b/libs/spandsp/src/t4_t6_decode.c @@ -95,9 +95,7 @@ #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" #include "spandsp/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" -#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" @@ -105,9 +103,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" -#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/image_translate.h" diff --git a/libs/spandsp/src/t4_t6_encode.c b/libs/spandsp/src/t4_t6_encode.c index 85838a0ea9..b092ecd3f0 100644 --- a/libs/spandsp/src/t4_t6_encode.c +++ b/libs/spandsp/src/t4_t6_encode.c @@ -92,9 +92,7 @@ #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" #include "spandsp/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" -#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" @@ -102,9 +100,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" -#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/image_translate.h" diff --git a/libs/spandsp/src/t4_tx.c b/libs/spandsp/src/t4_tx.c index 0c17b585f2..0d66d5690a 100644 --- a/libs/spandsp/src/t4_tx.c +++ b/libs/spandsp/src/t4_tx.c @@ -64,9 +64,7 @@ #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" #include "spandsp/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" -#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" @@ -74,9 +72,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -#if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" -#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/image_translate.h" @@ -168,7 +164,7 @@ static const TIFFFieldInfo tiff_fx_tiff_field_info[] = {TIFFTAG_IMAGELAYER, 2, 2, TIFF_LONG, FIELD_CUSTOM, false, false, (char *) "ImageLayer"}, }; -#if 1 +#if TIFFLIB_VERSION >= 20120615 static TIFFField tiff_fx_tiff_fields[] = { { TIFFTAG_INDEXED, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "Indexed" }, @@ -420,7 +416,7 @@ static int get_tiff_directory_info(t4_tx_state_t *s) float bmax; uint8_t parm8; #endif -#if defined(TIFFTAG_INDEXED) +#if defined(SPANDSP_SUPPORT_TIFF_FX) uint16_t parm16; #endif uint32_t parm32; @@ -457,7 +453,7 @@ static int get_tiff_directory_info(t4_tx_state_t *s) else return -1; -#if defined(TIFFTAG_INDEXED) +#if defined(SPANDSP_SUPPORT_TIFF_FX) parm16 = 0; if (TIFFGetField(t->tiff_file, TIFFTAG_INDEXED, &parm16)) { @@ -526,11 +522,9 @@ static int get_tiff_directory_info(t4_tx_state_t *s) case COMPRESSION_T85: span_log(&s->logging, SPAN_LOG_FLOW, "T.85\n"); break; -#if defined(SPANDSP_SUPPORT_T43) case COMPRESSION_T43: span_log(&s->logging, SPAN_LOG_FLOW, "T.43\n"); break; -#endif case COMPRESSION_JPEG: span_log(&s->logging, SPAN_LOG_FLOW, "JPEG\n"); if (t->photo_metric == PHOTOMETRIC_ITULAB) @@ -873,20 +867,20 @@ static int read_tiff_raw_image(t4_tx_state_t *s) total_len = 0; for (i = 0; i < num_strips; i++) total_len += TIFFRawStripSize(s->tiff.tiff_file, i); - if ((s->pre_encoded_buf = span_realloc(s->pre_encoded_buf, total_len)) == NULL) + if ((s->no_encoder.buf = span_realloc(s->no_encoder.buf, total_len)) == NULL) return -1; total_len = 0; for (i = 0; i < num_strips; i++, total_len += len) { len = TIFFRawStripSize(s->tiff.tiff_file, i); - if ((len = TIFFReadRawStrip(s->tiff.tiff_file, i, &s->pre_encoded_buf[total_len], len)) < 0) + if ((len = TIFFReadRawStrip(s->tiff.tiff_file, i, &s->no_encoder.buf[total_len], len)) < 0) { span_log(&s->logging, SPAN_LOG_WARNING, "%s: TIFFReadRawStrip error.\n", s->tiff.file); return -1; } } - s->pre_encoded_len = total_len; - s->pre_encoded_ptr = 0; + s->no_encoder.buf_len = total_len; + s->no_encoder.buf_ptr = 0; return 0; } /*- End of function --------------------------------------------------------*/ @@ -933,7 +927,7 @@ static int read_tiff_t85_image(t4_tx_state_t *s) pack.row = 0; t85_decode_init(&t85, packing_row_write_handler, &pack); t85_decode_set_comment_handler(&t85, 1000, embedded_comment_handler, s); - + t85_decode_set_image_size_constraints(&t85, s->tiff.image_width, s->tiff.image_length); result = -1; for (i = 0; i < num_strips; i++) { @@ -944,8 +938,7 @@ static int read_tiff_t85_image(t4_tx_state_t *s) span_free(raw_data); return -1; } - result = t85_decode_put(&t85, raw_data, len); - if (result != T4_DECODE_MORE_DATA) + if ((result = t85_decode_put(&t85, raw_data, len)) != T4_DECODE_MORE_DATA) break; } if (result == T4_DECODE_MORE_DATA) @@ -959,7 +952,6 @@ static int read_tiff_t85_image(t4_tx_state_t *s) } /*- End of function --------------------------------------------------------*/ -#if defined(SPANDSP_SUPPORT_T43) static int read_tiff_t43_image(t4_tx_state_t *s) { int biggest; @@ -1007,6 +999,7 @@ static int read_tiff_t43_image(t4_tx_state_t *s) t43_decode_init(&t43, packing_row_write_handler, &pack); t43_decode_set_comment_handler(&t43, 1000, embedded_comment_handler, NULL); + t43_decode_set_image_size_constraints(&t43, s->tiff.image_width, s->tiff.image_length); logging = t43_decode_get_logging_state(&t43); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); @@ -1025,8 +1018,7 @@ static int read_tiff_t43_image(t4_tx_state_t *s) span_free(raw_data); return -1; } - result = t43_decode_put(&t43, raw_data, len); - if (result != T4_DECODE_MORE_DATA) + if ((result = t43_decode_put(&t43, raw_data, len)) != T4_DECODE_MORE_DATA) break; } if (result == T4_DECODE_MORE_DATA) @@ -1037,7 +1029,6 @@ static int read_tiff_t43_image(t4_tx_state_t *s) return s->tiff.image_size; } /*- End of function --------------------------------------------------------*/ -#endif static int read_tiff_t42_t81_image(t4_tx_state_t *s) { @@ -1168,36 +1159,38 @@ static int read_tiff_image(t4_tx_state_t *s) int total_len; int i; int len; + int alter_image; uint8_t *t; if (s->metadata.image_type != s->tiff.image_type || s->metadata.image_width != s->tiff.image_width) { + /* We need to rework the image, so it can't pass directly through */ + alter_image = true; image_translate_restart(&s->translator, s->tiff.image_length); s->metadata.image_length = image_translate_get_output_length(&s->translator); + image_translate_set_row_read_handler(&s->translator, translate_row_read2, s); } else { + alter_image = false; s->metadata.image_length = s->tiff.image_length; } s->pack_buf = NULL; s->pack_ptr = 0; s->pack_row = 0; + s->apply_lab = false; if (s->tiff.image_type != T4_IMAGE_TYPE_BILEVEL) { /* If colour/gray scale is supported we may be able to send the image as it is, perhaps after a resizing. Otherwise we need to resize it, and squash it to a bilevel image. */ if (s->tiff.compression == COMPRESSION_JPEG && s->tiff.photo_metric == PHOTOMETRIC_ITULAB) { - if (s->metadata.image_type != s->tiff.image_type || s->metadata.image_width != s->tiff.image_width) + if (alter_image) { if (read_tiff_t42_t81_image(s) < 0) return -1; - s->pack_buf = s->tiff.image_buffer; - s->pack_ptr = 0; - s->pack_row = 0; - image_translate_set_row_read_handler(&s->translator, translate_row_read2, s); } else { @@ -1209,15 +1202,11 @@ static int read_tiff_image(t4_tx_state_t *s) #if defined(SPANDSP_SUPPORT_T43) else if (s->tiff.compression == COMPRESSION_T43) { - if (s->metadata.image_type != s->tiff.image_type || s->metadata.image_width != s->tiff.image_width) + if (alter_image) { if ((len = read_tiff_t43_image(s)) < 0) return -1; - s->pack_buf = s->tiff.image_buffer; - s->pack_ptr = 0; - s->pack_row = 0; - image_translate_set_row_read_handler(&s->translator, translate_row_read2, s); } else { @@ -1230,15 +1219,11 @@ static int read_tiff_image(t4_tx_state_t *s) #if defined(SPANDSP_SUPPORT_T45) else if (s->tiff.compression == COMPRESSION_T45) { - if (s->metadata.image_type != s->tiff.image_type || s->metadata.image_width != s->tiff.image_width) + if (alter_image) { if (read_tiff_t45_image(s) < 0) return -1; - s->pack_buf = s->tiff.image_buffer; - s->pack_ptr = 0; - s->pack_row = 0; - image_translate_set_row_read_handler(&s->translator, translate_row_read2, s); } else { @@ -1252,7 +1237,7 @@ static int read_tiff_image(t4_tx_state_t *s) { /* Let libtiff handle the decompression */ TIFFSetField(s->tiff.tiff_file, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); - if (s->metadata.image_type != s->tiff.image_type || s->metadata.image_width != s->tiff.image_width) + if (alter_image) { image_translate_set_row_read_handler(&s->translator, translate_row_read, s); } @@ -1262,6 +1247,7 @@ static int read_tiff_image(t4_tx_state_t *s) return -1; } } + set_image_width(s, s->metadata.image_width); set_image_length(s, s->metadata.image_length); t4_tx_set_image_type(s, s->metadata.image_type); @@ -1292,9 +1278,6 @@ static int read_tiff_image(t4_tx_state_t *s) set_lab_gamut(&s->lab_params, 0, 100, -85, 85, -75, 125, false); s->apply_lab = true; break; - default: - s->apply_lab = false; - break; } total_len = 0; for (i = 0; i < s->metadata.image_length; i++) @@ -1305,7 +1288,7 @@ static int read_tiff_image(t4_tx_state_t *s) } else { - if (s->metadata.image_type != s->tiff.image_type || s->metadata.image_width != s->tiff.image_width) + if (alter_image) { total_len = 0; s->tiff.image_buffer = span_realloc(s->tiff.image_buffer, s->metadata.image_width*s->metadata.image_length*3); @@ -1435,10 +1418,8 @@ static int set_row_read_handler(t4_tx_state_t *s, t4_row_read_handler_t handler, case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_SYCC_T81: return t42_encode_set_row_read_handler(&s->encoder.t42, handler, user_data); -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: return t43_encode_set_row_read_handler(&s->encoder.t43, handler, user_data); -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: return t45_encode_set_row_read_handler(&s->encoder.t45, handler, user_data); @@ -1674,7 +1655,7 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, int width_code; int res_code; /* Correct resolution code */ int alt_res_code; /* Fallback resolution code, where a metric/inch swap is possible */ - } width_info[] = + } width_and_res_info[] = { { T4_WIDTH_100_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_100_100, 0}, { T4_WIDTH_100_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_100_100, 0}, @@ -1777,7 +1758,9 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, int entry; int compression; int res; + int supported_colour_compressions; + supported_colour_compressions = supported_compressions & (T4_COMPRESSION_T42_T81 | T4_COMPRESSION_T43 | T4_COMPRESSION_T45 | T4_COMPRESSION_SYCC_T81); compression = -1; s->metadata.image_type = s->tiff.image_type; if (s->tiff.image_type != T4_IMAGE_TYPE_BILEVEL) @@ -1786,7 +1769,7 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, /* Can we send this page as it is? */ if (supported_colour_resolutions && - (supported_compressions & (T4_COMPRESSION_T42_T81 | T4_COMPRESSION_T43 | T4_COMPRESSION_T45 | T4_COMPRESSION_SYCC_T81)) + supported_colour_compressions && (((s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL || s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_8BIT || s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_12BIT) && @@ -1798,28 +1781,6 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, { /* Gray-scale/colour is possible */ span_log(&s->logging, SPAN_LOG_FLOW, "Gray-scale/colour is allowed\n"); - if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL - || - s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_8BIT - || - s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_12BIT) - { - if (!(supported_compressions & T4_COMPRESSION_COLOUR)) - { - span_log(&s->logging, SPAN_LOG_FLOW, "Colour is not allowed\n"); - return T4_IMAGE_FORMAT_INCOMPATIBLE; - } - } - else if (s->tiff.image_type == T4_IMAGE_TYPE_GRAY_8BIT - || - s->tiff.image_type == T4_IMAGE_TYPE_GRAY_12BIT) - { - if (!(supported_compressions & T4_COMPRESSION_GRAYSCALE)) - { - span_log(&s->logging, SPAN_LOG_FLOW, "Gray-scale is not allowed\n"); - return T4_IMAGE_FORMAT_INCOMPATIBLE; - } - } /* Choose the best gray-scale/colour encoding available to us */ if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL && (supported_compressions & T4_COMPRESSION_T43)) compression = T4_COMPRESSION_T43; @@ -1838,32 +1799,29 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, { /* Gray-scale/colour is not possible. Can we flatten the image to send it? */ span_log(&s->logging, SPAN_LOG_FLOW, "Gray-scale/colour is not allowed\n"); - if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL - || - s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_8BIT - || - s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_12BIT) + switch (s->tiff.image_type) { + case T4_IMAGE_TYPE_COLOUR_BILEVEL: + case T4_IMAGE_TYPE_COLOUR_8BIT: + case T4_IMAGE_TYPE_COLOUR_12BIT: if (!(supported_compressions & T4_COMPRESSION_COLOUR_TO_BILEVEL)) { span_log(&s->logging, SPAN_LOG_FLOW, "Flattening is not allowed\n"); return T4_IMAGE_FORMAT_INCOMPATIBLE; } - s->metadata.image_type = T4_IMAGE_TYPE_BILEVEL; - } - else if (s->tiff.image_type == T4_IMAGE_TYPE_GRAY_8BIT - || - s->tiff.image_type == T4_IMAGE_TYPE_GRAY_12BIT) - { + break; + case T4_IMAGE_TYPE_GRAY_8BIT: + case T4_IMAGE_TYPE_GRAY_12BIT: if (!(supported_compressions & T4_COMPRESSION_GRAY_TO_BILEVEL)) { span_log(&s->logging, SPAN_LOG_FLOW, "Flattening is not allowed\n"); return T4_IMAGE_FORMAT_INCOMPATIBLE; } - s->metadata.image_type = T4_IMAGE_TYPE_BILEVEL; + break; } /* Squashing to a bi-level image is possible */ - span_log(&s->logging, SPAN_LOG_FLOW, "The image may be flattened to %d\n", s->metadata.image_type); + s->metadata.image_type = T4_IMAGE_TYPE_BILEVEL; + span_log(&s->logging, SPAN_LOG_FLOW, "The image will be flattened to %s\n", t4_image_type_to_str(s->metadata.image_type)); } } @@ -1884,26 +1842,20 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, /* Deal with the image width/resolution combination. */ /* Look for a pattern that matches the image */ - res = T4_IMAGE_FORMAT_NOSIZESUPPORT; - for (entry = 0; s->tiff.image_width >= width_info[entry].width; entry++) + s->metadata.width_code = -1; + for (entry = 0; s->tiff.image_width >= width_and_res_info[entry].width; entry++) { - if (s->tiff.image_width == width_info[entry].width && s->tiff.resolution_code == width_info[entry].res_code) + if (s->tiff.image_width == width_and_res_info[entry].width && s->tiff.resolution_code == width_and_res_info[entry].res_code) { - res = T4_IMAGE_FORMAT_OK; + s->metadata.width_code = width_and_res_info[entry].width_code; break; } } - - s->metadata.width_code = width_info[entry].width_code; - + res = T4_IMAGE_FORMAT_NOSIZESUPPORT; s->row_squashing_ratio = 1; - if (res == T4_IMAGE_FORMAT_OK) + if (s->metadata.width_code >= 0 && (supported_image_sizes & s->metadata.width_code)) { - /* We have a valid width/resolution combination */ - - /* Check if this width/resolution combination is supported */ - if (!(supported_image_sizes & width_info[entry].width_code)) - return T4_IMAGE_FORMAT_NOSIZESUPPORT; + /* We have a valid and supported width/resolution combination */ /* No resize necessary */ s->metadata.image_width = s->tiff.image_width; @@ -1912,7 +1864,7 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, res = T4_IMAGE_FORMAT_NORESSUPPORT; if (s->metadata.image_type == T4_IMAGE_TYPE_BILEVEL) { - if ((width_info[entry].res_code & supported_bilevel_resolutions)) + if ((width_and_res_info[entry].res_code & supported_bilevel_resolutions)) { /* We can use the resolution of the original image */ s->metadata.resolution_code = s->tiff.resolution_code; @@ -1920,56 +1872,51 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code); res = T4_IMAGE_FORMAT_OK; } + else if ((width_and_res_info[entry].alt_res_code & supported_bilevel_resolutions)) + { + /* We can do a metric/imperial swap, and have a usable resolution */ + span_log(&s->logging, + SPAN_LOG_FLOW, + "Image resolution %s falls back to %s\n", + t4_image_resolution_to_str(s->tiff.resolution_code), + t4_image_resolution_to_str(width_and_res_info[entry].alt_res_code)); + s->metadata.resolution_code = width_and_res_info[entry].alt_res_code; + s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code); + s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code); + res = T4_IMAGE_FORMAT_OK; + } else { - /* The resolution is not supported, but there might be an approximation, or a length - squashing that might work. */ - if ((width_info[entry].alt_res_code & supported_bilevel_resolutions)) + if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL) { - /* We can do a metric/imperial swap, and have a usable resolution */ - span_log(&s->logging, - SPAN_LOG_FLOW, - "Image resolution %s falls back to %s\n", - t4_image_resolution_to_str(s->tiff.resolution_code), - t4_image_resolution_to_str(width_info[entry].alt_res_code)); - s->metadata.resolution_code = width_info[entry].alt_res_code; - s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code); - s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code); - res = T4_IMAGE_FORMAT_OK; - } - else - { - if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL) + if ((s->tiff.resolution_code & (T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE))) { - if ((s->tiff.resolution_code & (T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE))) + /* This might be a resolution we can squash down to something which is supported */ + for (i = 0; i < 4; i++) { - /* This might be a resolution we can squash down to something which is supported */ - for (i = 0; i < 4; i++) + if ((s->tiff.resolution_code & squashable[i].resolution)) + break; + } + if (i < 4) + { + /* This is a squashable resolution, so let's see if there is a valid + fallback we can squash the image to, scanning through the entries + in their order of preference. */ + for (j = 0; j < 4; j++) { - if ((s->tiff.resolution_code & squashable[i].resolution)) - break; - } - if (i < 4) - { - /* This is a squashable resolution, so let's see if there is a valid - fallback we can squash the image to, scanning through the entries - in their order of preference. */ - for (j = 0; j < 4; j++) + if ((supported_bilevel_resolutions & squashable[i].fallback[j].resolution)) { - if ((supported_bilevel_resolutions & squashable[i].fallback[j].resolution)) - { - span_log(&s->logging, - SPAN_LOG_FLOW, - "Image resolution %s falls back to %s\n", - t4_image_resolution_to_str(s->tiff.resolution_code), - t4_image_resolution_to_str(squashable[i].fallback[j].resolution)); - s->row_squashing_ratio = squashable[i].fallback[j].squashing_factor; - s->metadata.resolution_code = squashable[i].fallback[j].resolution; - s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code); - s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code); - res = T4_IMAGE_FORMAT_OK; - break; - } + span_log(&s->logging, + SPAN_LOG_FLOW, + "Image resolution %s falls back to %s\n", + t4_image_resolution_to_str(s->tiff.resolution_code), + t4_image_resolution_to_str(squashable[i].fallback[j].resolution)); + s->row_squashing_ratio = squashable[i].fallback[j].squashing_factor; + s->metadata.resolution_code = squashable[i].fallback[j].resolution; + s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code); + s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code); + res = T4_IMAGE_FORMAT_OK; + break; } } } @@ -1977,25 +1924,25 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, } } /* If we have not succeeded in matching up the size and resolution, the next step will - depend on whether the original was a bi-level image. If it was we are stuck, as you can't + depend on whether the original was a bi-level image. If it was, we are stuck, as you can't really resize those. If it was not, a resize might be possible */ if (res != T4_IMAGE_FORMAT_OK) { if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL) return T4_IMAGE_FORMAT_NORESSUPPORT; if (!(supported_compressions & T4_COMPRESSION_RESCALING)) - return T4_IMAGE_FORMAT_NORESSUPPORT; + return T4_IMAGE_FORMAT_NOSIZESUPPORT; } /* TODO */ } else { - if ((width_info[entry].res_code & supported_bilevel_resolutions)) + if ((width_and_res_info[entry].res_code & supported_bilevel_resolutions)) { if ((s->tiff.resolution_code & supported_colour_resolutions)) { /* We can use the resolution of the original image */ - s->metadata.resolution_code = width_info[entry].res_code; + s->metadata.resolution_code = width_and_res_info[entry].res_code; s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code); s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code); res = T4_IMAGE_FORMAT_OK; @@ -2007,12 +1954,13 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, { /* Can we rework the image to fit? */ /* We can't rework a bilevel image that fits none of the patterns */ - if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL) + if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL || s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL) return T4_IMAGE_FORMAT_NORESSUPPORT; if (!(supported_compressions & T4_COMPRESSION_RESCALING)) - return T4_IMAGE_FORMAT_NORESSUPPORT; - res = T4_IMAGE_FORMAT_OK; + return T4_IMAGE_FORMAT_NOSIZESUPPORT; /* Any other kind of image might be resizable */ + res = T4_IMAGE_FORMAT_OK; + /* TODO: use more sophisticated resizing */ s->metadata.image_width = T4_WIDTH_200_A4; s->metadata.resolution_code = T4_RESOLUTION_200_200; s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code); @@ -2103,7 +2051,6 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, s->metadata.compression = compression; res = T4_IMAGE_FORMAT_OK; break; -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: switch (s->metadata.compression) { @@ -2116,7 +2063,6 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, s->metadata.compression = compression; res = T4_IMAGE_FORMAT_OK; break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: switch (s->metadata.compression) @@ -2215,11 +2161,9 @@ static void set_image_width(t4_tx_state_t *s, uint32_t image_width) case T4_COMPRESSION_SYCC_T81: t42_encode_set_image_width(&s->encoder.t42, image_width); break; -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: t43_encode_set_image_width(&s->encoder.t43, image_width); break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: t45_encode_set_image_width(&s->encoder.t45, image_width); @@ -2252,11 +2196,9 @@ static void set_image_length(t4_tx_state_t *s, uint32_t image_length) case T4_COMPRESSION_SYCC_T81: t42_encode_set_image_length(&s->encoder.t42, image_length); break; -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: t43_encode_set_image_length(&s->encoder.t43, image_length); break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: t45_encode_set_image_length(&s->encoder.t45, image_length); @@ -2280,11 +2222,9 @@ static void t4_tx_set_image_type(t4_tx_state_t *s, int image_type) case T4_COMPRESSION_SYCC_T81: t42_encode_set_image_type(&s->encoder.t42, image_type); break; -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: t43_encode_set_image_type(&s->encoder.t43, image_type); break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: t45_encode_set_image_type(&s->encoder.t45, image_type); @@ -2410,13 +2350,11 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t t->length = t42_encode_get_image_length(&s->encoder.t42); t->line_image_size = t42_encode_get_compressed_image_size(&s->encoder.t42)/8; break; -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: t->width = t43_encode_get_image_width(&s->encoder.t43); t->length = t43_encode_get_image_length(&s->encoder.t43); t->line_image_size = t43_encode_get_compressed_image_size(&s->encoder.t43)/8; break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: t->width = t45_encode_get_image_width(&s->encoder.t45); @@ -2430,9 +2368,9 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t SPAN_DECLARE(int) t4_tx_image_complete(t4_tx_state_t *s) { - if (s->pre_encoded_len > 0) + if (s->no_encoder.buf_len > 0) { - if (s->pre_encoded_ptr >= s->pre_encoded_len) + if (s->no_encoder.buf_ptr >= s->no_encoder.buf_len) return SIG_STATUS_END_OF_DATA; return 0; } @@ -2453,10 +2391,8 @@ SPAN_DECLARE(int) t4_tx_image_complete(t4_tx_state_t *s) case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_SYCC_T81: return t42_encode_image_complete(&s->encoder.t42); -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: return t43_encode_image_complete(&s->encoder.t43); -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: return t45_encode_image_complete(&s->encoder.t45); @@ -2471,15 +2407,15 @@ SPAN_DECLARE(int) t4_tx_get_bit(t4_tx_state_t *s) int bit; /* We only get bit by bit for T.4 1D and T.4 2-D. */ - if (s->pre_encoded_len > 0) + if (s->no_encoder.buf_len > 0) { - if (s->pre_encoded_ptr >= s->pre_encoded_len) + if (s->no_encoder.buf_ptr >= s->no_encoder.buf_len) return SIG_STATUS_END_OF_DATA; - bit = (s->pre_encoded_buf[s->pre_encoded_ptr] >> s->pre_encoded_bit) & 1; - if (++s->pre_encoded_bit >= 8) + bit = (s->no_encoder.buf[s->no_encoder.buf_ptr] >> s->no_encoder.bit) & 1; + if (++s->no_encoder.bit >= 8) { - s->pre_encoded_bit = 0; - s->pre_encoded_ptr++; + s->no_encoder.bit = 0; + s->no_encoder.buf_ptr++; } return bit; } @@ -2489,12 +2425,12 @@ SPAN_DECLARE(int) t4_tx_get_bit(t4_tx_state_t *s) SPAN_DECLARE(int) t4_tx_get(t4_tx_state_t *s, uint8_t buf[], size_t max_len) { - if (s->pre_encoded_len > 0) + if (s->no_encoder.buf_len > 0) { - if (max_len > (s->pre_encoded_len - s->pre_encoded_ptr)) - max_len = s->pre_encoded_len - s->pre_encoded_ptr; - memcpy(buf, &s->pre_encoded_buf[s->pre_encoded_ptr], max_len); - s->pre_encoded_ptr += max_len; + if (max_len > (s->no_encoder.buf_len - s->no_encoder.buf_ptr)) + max_len = s->no_encoder.buf_len - s->no_encoder.buf_ptr; + memcpy(buf, &s->no_encoder.buf[s->no_encoder.buf_ptr], max_len); + s->no_encoder.buf_ptr += max_len; return max_len; } @@ -2547,12 +2483,10 @@ SPAN_DECLARE(int) t4_tx_start_page(t4_tx_state_t *s) t42_encode_restart(&s->encoder.t42, s->metadata.image_width, s->metadata.image_length); s->image_get_handler = (t4_image_get_handler_t) t42_encode_get; break; -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: t43_encode_restart(&s->encoder.t43, s->metadata.image_width, s->metadata.image_length); s->image_get_handler = (t4_image_get_handler_t) t43_encode_get; break; -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: t45_encode_restart(&s->encoder.t45, s->metadata.image_width, s->metadata.image_length); @@ -2684,10 +2618,8 @@ SPAN_DECLARE(int) t4_tx_release(t4_tx_state_t *s) case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_SYCC_T81: return t42_encode_release(&s->encoder.t42); -#if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: return t43_encode_release(&s->encoder.t43); -#endif #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: return t45_encode_release(&s->encoder.t45); diff --git a/libs/spandsp/src/t85_decode.c b/libs/spandsp/src/t85_decode.c index 8af029d3a0..82bbecf013 100644 --- a/libs/spandsp/src/t85_decode.c +++ b/libs/spandsp/src/t85_decode.c @@ -53,7 +53,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -static __inline__ int32_t pack_32(uint8_t *s) +static __inline__ int32_t pack_32(const uint8_t *s) { int32_t value; @@ -265,6 +265,16 @@ static int finish_sde(t85_decode_state_t *s) } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(bool) t85_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len) +{ + if (len < 20) + return false; + *width = pack_32(&data[6]); + *length = pack_32(&data[10]); + return true; +} +/*- End of function --------------------------------------------------------*/ + static int check_bih(t85_decode_state_t *s) { /* Check that the fixed parameters have the values they are expected to be @@ -289,12 +299,14 @@ static int check_bih(t85_decode_state_t *s) #endif { span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. Fixed bytes do not contain expected values.\n"); + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; } /* P - Number of bit planes */ if (s->buffer[2] < s->min_bit_planes || s->buffer[2] > s->max_bit_planes) { span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. %d bit planes. Should be %d to %d.\n", s->buffer[2], s->min_bit_planes, s->max_bit_planes); + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; } s->bit_planes = s->buffer[2]; @@ -305,6 +317,7 @@ static int check_bih(t85_decode_state_t *s) if (s->xd == 0 || (s->max_xd && s->xd > s->max_xd)) { span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. Width is %" PRIu32 "\n", s->xd); + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; } /* YD - Vertical image size at layer D */ @@ -312,6 +325,7 @@ static int check_bih(t85_decode_state_t *s) if (s->yd == 0 || (s->max_yd && s->yd > s->max_yd)) { span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. Length is %" PRIu32 "\n", s->yd); + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; } /* L0 - Rows per stripe, at the lowest resolution */ @@ -319,6 +333,7 @@ static int check_bih(t85_decode_state_t *s) if (s->l0 == 0) { span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. L0 is %" PRIu32 "\n", s->l0); + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; } /* MX - Maximum horizontal offset allowed for AT pixel */ @@ -326,6 +341,7 @@ static int check_bih(t85_decode_state_t *s) if (s->mx > 127) { span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. MX is %d\n", s->mx); + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; } /* Options byte */ @@ -333,6 +349,7 @@ static int check_bih(t85_decode_state_t *s) if ((s->options & 0x97)) { span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. Options are 0x%X\n", s->options); + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; } span_log(&s->logging, SPAN_LOG_FLOW, "BIH is OK. Image is %" PRIu32 "x%" PRIu32 " pixels\n", s->xd, s->yd); @@ -378,6 +395,8 @@ SPAN_DECLARE(int) t85_decode_put(t85_decode_state_t *s, const uint8_t data[], si { if (s->y >= s->yd) return T4_DECODE_OK; + if (s->end_of_data > 0) + return T4_DECODE_INVALID_DATA; /* This is the end of image condition */ s->end_of_data = 1; } @@ -492,7 +511,6 @@ SPAN_DECLARE(int) t85_decode_put(t85_decode_state_t *s, const uint8_t data[], si the commonest thing for us to hit here. */ decode_pscd(s, s->buffer, 2); s->buf_len = 0; - if (s->interrupt) return T4_DECODE_INTERRUPT; break; @@ -523,9 +541,11 @@ SPAN_DECLARE(int) t85_decode_put(t85_decode_state_t *s, const uint8_t data[], si continue; s->buf_needed = 2; s->buf_len = 0; - if (s->at_moves >= T85_ATMOVES_MAX) + { + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; + } s->at_row[s->at_moves] = pack_32(&s->buffer[2]); s->at_tx[s->at_moves] = s->buffer[6]; if (s->at_tx[s->at_moves] > s->mx @@ -534,6 +554,7 @@ SPAN_DECLARE(int) t85_decode_put(t85_decode_state_t *s, const uint8_t data[], si || s->buffer[7] != 0) { + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; } s->at_moves++; @@ -544,14 +565,19 @@ SPAN_DECLARE(int) t85_decode_put(t85_decode_state_t *s, const uint8_t data[], si continue; s->buf_needed = 2; s->buf_len = 0; - if (!(s->options & T85_VLENGTH)) + { + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; + } s->options &= ~T85_VLENGTH; y = pack_32(&s->buffer[2]); /* An update to the image length is not allowed to stretch it. */ if (y > s->yd) + { + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; + } s->yd = y; break; case T82_SDNORM: @@ -633,7 +659,10 @@ SPAN_DECLARE(int) t85_decode_put(t85_decode_state_t *s, const uint8_t data[], si y = pack_32(&s->buffer[4]); /* An update to the image length is not allowed to stretch it. */ if (y > s->yd) + { + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; + } /* Things look OK, so accept this new length, and proceed. */ s->yd = y; /* Now process the T82_SDNORM or T82_SDRST */ @@ -647,6 +676,7 @@ SPAN_DECLARE(int) t85_decode_put(t85_decode_state_t *s, const uint8_t data[], si break; default: s->buf_len = 0; + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; } } @@ -663,10 +693,12 @@ SPAN_DECLARE(int) t85_decode_put(t85_decode_state_t *s, const uint8_t data[], si /* We should only have stopped processing PSCD if we ran out of data, or hit a T82_ESC */ if (cnt < len && data[cnt] != T82_ESC) + { + s->end_of_data = 2; return T4_DECODE_INVALID_DATA; + } } } - return T4_DECODE_MORE_DATA; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/tests/Makefile.am b/libs/spandsp/tests/Makefile.am index 881a4839b5..7149900a90 100644 --- a/libs/spandsp/tests/Makefile.am +++ b/libs/spandsp/tests/Makefile.am @@ -50,6 +50,14 @@ AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_builddir)/spandsp-sim -DDATADIR="\"$ LIBDIR = -L$(top_builddir)/src +if COND_V32BIS +V32BIS_PROGS = v32bis_tests +endif + +if COND_V34 +V34_PROGS = v34_tests +endif + noinst_PROGRAMS = ademco_contactid_tests \ adsi_tests \ alloc_tests \ @@ -94,6 +102,7 @@ noinst_PROGRAMS = ademco_contactid_tests \ playout_tests \ plc_tests \ power_meter_tests \ + pseudo_terminal_tests \ queue_tests \ r2_mf_rx_tests \ r2_mf_tx_tests \ @@ -130,7 +139,9 @@ noinst_PROGRAMS = ademco_contactid_tests \ v42bis_tests \ v8_tests \ vector_float_tests \ - vector_int_tests + vector_int_tests \ + $(V32BIS_PROGS) \ + $(V34_PROGS) noinst_HEADERS = echo_monitor.h \ fax_tester.h \ @@ -139,6 +150,7 @@ noinst_HEADERS = echo_monitor.h \ media_monitor.h \ modem_monitor.h \ pcap_parse.h \ + pseudo_terminals.h \ udptl.h ademco_contactid_tests_SOURCES = ademco_contactid_tests.c @@ -273,6 +285,9 @@ plc_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspands power_meter_tests_SOURCES = power_meter_tests.c power_meter_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp +pseudo_terminal_tests_SOURCES = pseudo_terminal_tests.c fax_utils.c pseudo_terminals.c +pseudo_terminal_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim -lspandsp -lutil + queue_tests_SOURCES = queue_tests.c queue_tests_LDADD = $(LIBDIR) -lspandsp @@ -369,6 +384,16 @@ v27ter_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspa v29_tests_SOURCES = v29_tests.c line_model_monitor.cpp modem_monitor.cpp v29_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp +if COND_V32BIS +v32bis_tests_SOURCES = v32bis_tests.c line_model_monitor.cpp modem_monitor.cpp +v32bis_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp +endif + +if COND_V34 +v34_tests_SOURCES = v34_tests.c line_model_monitor.cpp modem_monitor.cpp +v34_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp +endif + v42_tests_SOURCES = v42_tests.c v42_tests_LDADD = $(LIBDIR) -lspandsp diff --git a/libs/spandsp/tests/alloc_tests.c b/libs/spandsp/tests/alloc_tests.c index 0e8177ae29..2f64e6ae27 100644 --- a/libs/spandsp/tests/alloc_tests.c +++ b/libs/spandsp/tests/alloc_tests.c @@ -58,9 +58,10 @@ int main(int argc, char *argv[]) void *b; void *c; - if (span_mem_allocators(memalign, - malloc, + if (span_mem_allocators(malloc, realloc, + free, + memalign, free)) { printf("Failed\n"); @@ -70,7 +71,7 @@ int main(int argc, char *argv[]) b = span_alloc(42); c = span_realloc(NULL, 42); printf("%p %p %p\n", a, b, c); - span_free(a); + span_aligned_free(a); span_free(b); span_free(c); } diff --git a/libs/spandsp/tests/fax_tests.c b/libs/spandsp/tests/fax_tests.c index 7cbe61fcfa..5f8ce070e2 100644 --- a/libs/spandsp/tests/fax_tests.c +++ b/libs/spandsp/tests/fax_tests.c @@ -463,8 +463,8 @@ int main(int argc, char *argv[]) int outframes; SNDFILE *wave_handle; SNDFILE *input_wave_handle; - int use_ecm; - int use_tep; + bool use_ecm; + bool use_tep; int feedback_audio; int use_transmit_on_idle; int t38_version; @@ -479,7 +479,6 @@ int main(int argc, char *argv[]) double tx_when; double rx_when; int supported_modems; - int remove_fill_bits; int opt; int start_page; int end_page; @@ -490,8 +489,11 @@ int main(int argc, char *argv[]) int noise_level; int code_to_look_up; int scan_line_time; - int allowed_bilevel_resolutions; - int colour_enabled; + int allowed_bilevel_resolutions[2]; + int allowed; + bool remove_fill_bits; + bool colour_enabled; + bool t37_like_output; t38_stats_t t38_stats; t30_stats_t t30_stats; logging_state_t *logging; @@ -530,15 +532,22 @@ int main(int argc, char *argv[]) scan_line_time = 0; decode_file_name = NULL; code_to_look_up = -1; - allowed_bilevel_resolutions = 0; + allowed_bilevel_resolutions[0] = 0; + allowed_bilevel_resolutions[1] = 0; + allowed = 0; colour_enabled = false; + t37_like_output = false; t38_transport = T38_TRANSPORT_UDPTL; - while ((opt = getopt(argc, argv, "b:c:Cd:D:efFgH:i:Ilm:M:n:p:s:S:tT:u:v:z:")) != -1) + while ((opt = getopt(argc, argv, "7b:c:Cd:D:efFgH:i:Ilm:M:n:p:s:S:tT:u:v:z:")) != -1) { switch (opt) { + case '7': + t37_like_output = true; + break; case 'b': - allowed_bilevel_resolutions = atoi(optarg); + allowed_bilevel_resolutions[allowed] = atoi(optarg); + allowed ^= 1; break; case 'c': code_to_look_up = atoi(optarg); @@ -855,7 +864,7 @@ int main(int argc, char *argv[]) | T4_SUPPORT_LENGTH_US_LETTER | T4_SUPPORT_LENGTH_US_LEGAL | T4_SUPPORT_LENGTH_UNLIMITED); - switch (allowed_bilevel_resolutions) + switch (allowed_bilevel_resolutions[i]) { case 0: /* Allow anything */ @@ -926,7 +935,21 @@ int main(int argc, char *argv[]) { t30_set_supported_colour_resolutions(t30_state[i], 0); } - t30_set_supported_output_compressions(t30_state[i], T4_COMPRESSION_T6 | T4_COMPRESSION_JPEG); + if (t37_like_output) + { + t30_set_supported_output_compressions(t30_state[i], + T4_COMPRESSION_T85 + | T4_COMPRESSION_T85_L0 + | T4_COMPRESSION_T6 + | T4_COMPRESSION_T42_T81); + } + else + { + t30_set_supported_output_compressions(t30_state[i], + T4_COMPRESSION_T6 + | T4_COMPRESSION_JPEG); + } + t30_set_ecm_capability(t30_state[i], use_ecm); t30_set_supported_compressions(t30_state[i], T4_COMPRESSION_T4_1D diff --git a/libs/spandsp/tests/fax_tests.sh b/libs/spandsp/tests/fax_tests.sh index b09609e3f3..a4d36ce501 100755 --- a/libs/spandsp/tests/fax_tests.sh +++ b/libs/spandsp/tests/fax_tests.sh @@ -28,7 +28,7 @@ run_fax_test() fi # Now use tiffcmp to check the results. It will return non-zero if any page images differ. The -t # option means the normal differences in tags will be ignored. - tiffcmp -t ${FILE} fax_tests.tif >/dev/null + ${TIFFCMP} -t ${FILE} fax_tests.tif >/dev/null RETVAL=$? if [ $RETVAL != 0 ] then @@ -43,7 +43,7 @@ run_fax_squash_test() { # Test with lengthwise squashing of a bilevel image rm -f fax_tests.tif - echo ./fax_tests -b ${SQ} ${OPTS} -i ${IN_FILE} + echo ./fax_tests -b ${SQ} -b ${SQ} ${OPTS} -i ${IN_FILE} ./fax_tests -b ${SQ} ${OPTS} -i ${IN_FILE} >xyzzy 2>xyzzy2 RETVAL=$? if [ $RETVAL != 0 ] @@ -53,7 +53,7 @@ run_fax_squash_test() fi # Now use tiffcmp to check the results. It will return non-zero if any page images differ. The -t # option means the normal differences in tags will be ignored. - tiffcmp -t ${OUT_FILE} fax_tests.tif >/dev/null + ${TIFFCMP} -t ${OUT_FILE} fax_tests.tif >/dev/null RETVAL=$? if [ $RETVAL != 0 ] then @@ -77,7 +77,7 @@ run_colour_fax_test() fi # Now use tiffcmp to check the results. It will return non-zero if any page images differ. The -t # option means the normal differences in tags will be ignored. - tiffcmp -t ${OUT_FILE} fax_tests.tif >/dev/null + ${TIFFCMP} -t ${OUT_FILE} fax_tests.tif >/dev/null RETVAL=$? if [ $RETVAL != 0 ] then @@ -91,40 +91,35 @@ run_colour_fax_test() ITUTESTS_DIR=../test-data/itu/fax TIFFFX_DIR=../test-data/itu/tiff-fx LOCALTESTS_DIR=../test-data/local +TIFFCMP=tiffcmp # Colour/gray -> bilevel by not allowing ECM for OPTS in "-p AA" "-p TT" "-p GG" "-p TG" "-p GT" do - echo Colour to bi-level tests disabled -# IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif" -# OUT_FILE="${LOCALTESTS_DIR}/lenna-colour-bilevel.tif" -# run_colour_fax_test + IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif" + OUT_FILE="${LOCALTESTS_DIR}/lenna-colour-bilevel.tif" + run_colour_fax_test -# IN_FILE="${LOCALTESTS_DIR}/lenna-bw.tif" -# OUT_FILE="${LOCALTESTS_DIR}/lenna-bw-bilevel.tif" -# run_colour_fax_test + IN_FILE="${LOCALTESTS_DIR}/lenna-bw.tif" + OUT_FILE="${LOCALTESTS_DIR}/lenna-bw-bilevel.tif" + run_colour_fax_test -# IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif" -# OUT_FILE="${LOCALTESTS_DIR}/lenna-bw-bilevel.tif" -# run_colour_fax_test + IN_FILE="${TIFFFX_DIR}/c03x_02x.tif" + OUT_FILE="${TIFFFX_DIR}/c03x_02x-bilevel.tif" + run_colour_fax_test -# IN_FILE="${TIFFFX_DIR}/c03x_02x.tif" -# OUT_FILE="${TIFFFX_DIR}/c03x_02x.tif" -# run_colour_fax_test + IN_FILE="${TIFFFX_DIR}/l02x_02x.tif" + OUT_FILE="${TIFFFX_DIR}/l02x_02x-bilevel.tif" + run_colour_fax_test -# IN_FILE="${TIFFFX_DIR}/l02x_02x.tif" -# OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif" -# run_colour_fax_test - -# IN_FILE="${TIFFFX_DIR}/l04x_02x.tif" -# OUT_FILE="${TIFFFX_DIR}/l04x_02x.tif" -# run_colour_fax_test + IN_FILE="${TIFFFX_DIR}/l04x_02x.tif" + OUT_FILE="${TIFFFX_DIR}/l04x_02x-bilevel.tif" + run_colour_fax_test done # Colour/gray -> colour/gray for OPTS in "-p AA -C -e" "-p TT -C -e" "-p GG -C -e" "-p TG -C -e" "-p GT -C -e" do - echo Colour to colour tests disabled # IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif" # OUT_FILE="${LOCALTESTS_DIR}/lenna-colour-out.tif" # run_colour_fax_test @@ -137,9 +132,9 @@ do # OUT_FILE="${TIFFFX_DIR}/c03x_02x-out.tif" # run_colour_fax_test -# IN_FILE="${TIFFFX_DIR}/l02x_02x.tif" -# OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif" -# run_colour_fax_test + IN_FILE="${TIFFFX_DIR}/l02x_02x.tif" + OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif" + run_colour_fax_test # IN_FILE="${TIFFFX_DIR}/l04x_02x.tif" # OUT_FILE="${TIFFFX_DIR}/l04x_02x.tif" diff --git a/libs/spandsp/tests/pseudo_terminals_tests.c b/libs/spandsp/tests/pseudo_terminal_tests.c similarity index 53% rename from libs/spandsp/tests/pseudo_terminals_tests.c rename to libs/spandsp/tests/pseudo_terminal_tests.c index a4675c6c5b..b6d28d2b26 100644 --- a/libs/spandsp/tests/pseudo_terminals_tests.c +++ b/libs/spandsp/tests/pseudo_terminal_tests.c @@ -1,7 +1,7 @@ /* * SpanDSP - a series of DSP components for telephony * - * pseudo_terminals_tests.c - pseudo terminal handling tests. + * pseudo_terminal_tests.c - pseudo terminal handling tests. * * Written by Steve Underwood * @@ -31,7 +31,6 @@ #else #if defined(__APPLE__) #include -#include #elif defined(__FreeBSD__) #include #include @@ -39,33 +38,113 @@ #else #include #endif +#include +#include #include +#include #include #include +#include #endif #include "spandsp.h" +#include "spandsp/t30_fcf.h" + +#include "spandsp-sim.h" + +#undef SPANDSP_EXPOSE_INTERNAL_STRUCTURES + #include "pseudo_terminals.h" -int main(int argc, char *argv[]) +static int master(void) { modem_t modem[10]; + char buf[1024]; + int len; int i; for (i = 0; i < 10; i++) { if (psuedo_terminal_create(&modem[i])) + { printf("Failure\n"); + exit(2); + } printf("%s %s\n", modem[i].devlink, modem[i].stty); } - getchar(); + + for (;;) + { + for (i = 0; i < 10; i++) + { + len = read(modem[i].master, buf, 4); + if (len >= 0) + { + buf[len] = '\0'; + printf("%d %d '%s' %s\n", i, len, buf, strerror(errno)); + } + } + } + for (i = 0; i < 10; i++) { if (psuedo_terminal_close(&modem[i])) + { printf("Failure\n"); + exit(2); + } } return 0; } /*- End of function --------------------------------------------------------*/ + +static int slave(void) +{ + int fd[10]; + char name[64]; + int i; + int j; + + for (i = 0; i < 10; i++) + { + sprintf(name, "/dev/spandsp/%d", i); + if ((fd[i] = open(name, O_RDWR)) < 0) + { + printf("Failed to open %s\n", name); + exit(2); + } + printf("%s\n", name); + } + + for (j = 0; j < 10; j++) + { + for (i = 0; i < 10; i++) + { + write(fd[i], "FRED", 4); + } + } + + for (i = 0; i < 10; i++) + { + if (close(fd[i])) + { + printf("Failed to close %d\n", i); + exit(2); + } + } + + return 0; +} +/*- End of function --------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + if (argc < 2) + master(); + else + slave(); + return 0; +} +/*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/tests/pseudo_terminals.c b/libs/spandsp/tests/pseudo_terminals.c index c7bc2e67eb..1f042be8b9 100644 --- a/libs/spandsp/tests/pseudo_terminals.c +++ b/libs/spandsp/tests/pseudo_terminals.c @@ -51,6 +51,7 @@ #include "pseudo_terminals.h" int next_id = 0; +const char *device_root_name = "/dev/spandsp"; int psuedo_terminal_close(modem_t *modem) { @@ -175,7 +176,7 @@ int psuedo_terminal_create(modem_t *modem) modem->threadAbort = CreateEvent(NULL, true, false, NULL); #else modem->slot = next_id++; - snprintf(modem->devlink, sizeof(modem->devlink), "/dev/spandsp/%d", modem->slot); + snprintf(modem->devlink, sizeof(modem->devlink), "%s/%d", device_root_name, modem->slot); /* Remove any stale link which might be present */ unlink(modem->devlink); diff --git a/libs/spandsp/tests/t31_pseudo_terminal_tests.c b/libs/spandsp/tests/t31_pseudo_terminal_tests.c index 7c0825e4b5..d4fc01efc3 100644 --- a/libs/spandsp/tests/t31_pseudo_terminal_tests.c +++ b/libs/spandsp/tests/t31_pseudo_terminal_tests.c @@ -47,8 +47,6 @@ #include "spandsp.h" -#include "spandsp/t30_fcf.h" - #include "spandsp-sim.h" #undef SPANDSP_EXPOSE_INTERNAL_STRUCTURES diff --git a/libs/spandsp/tests/t38_decode.c b/libs/spandsp/tests/t38_decode.c index 34f072b781..e29b64cbf6 100644 --- a/libs/spandsp/tests/t38_decode.c +++ b/libs/spandsp/tests/t38_decode.c @@ -440,7 +440,36 @@ int main(int argc, char *argv[]) t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A'); t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A'); t30_set_ecm_capability(t30, use_ecm); - t30_set_supported_compressions(t30, T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6 | T4_COMPRESSION_T85); + t30_set_supported_compressions(t30, + T4_COMPRESSION_T4_1D + | T4_COMPRESSION_T4_2D + | T4_COMPRESSION_T6 + | T4_COMPRESSION_T85 + | T4_COMPRESSION_T85_L0 + | T4_COMPRESSION_T42_T81 + | T4_COMPRESSION_COLOUR); + t30_set_supported_bilevel_resolutions(t30, + T4_RESOLUTION_R8_STANDARD + | T4_RESOLUTION_R8_FINE + | T4_RESOLUTION_R8_SUPERFINE + | T4_RESOLUTION_R16_SUPERFINE + | T4_RESOLUTION_200_100 + | T4_RESOLUTION_200_200 + | T4_RESOLUTION_200_400 + | T4_RESOLUTION_300_300 + | T4_RESOLUTION_300_600 + | T4_RESOLUTION_400_400 + | T4_RESOLUTION_400_800 + | T4_RESOLUTION_600_600 + | T4_RESOLUTION_600_1200 + | T4_RESOLUTION_1200_1200); + t30_set_supported_colour_resolutions(t30, + T4_RESOLUTION_100_100 + | T4_RESOLUTION_200_200 + | T4_RESOLUTION_300_300 + | T4_RESOLUTION_400_400 + | T4_RESOLUTION_600_600 + | T4_RESOLUTION_1200_1200); if (pcap_scan_pkts(input_file_name, src_addr, src_port, dest_addr, dest_port, t38_terminal_timing_update, process_packet, NULL)) exit(2); @@ -497,7 +526,36 @@ int main(int argc, char *argv[]) t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'B'); t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'B'); t30_set_ecm_capability(t30, use_ecm); - t30_set_supported_compressions(t30, T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6); + t30_set_supported_compressions(t30, + T4_COMPRESSION_T4_1D + | T4_COMPRESSION_T4_2D + | T4_COMPRESSION_T6 + | T4_COMPRESSION_T85 + | T4_COMPRESSION_T85_L0 + | T4_COMPRESSION_T42_T81 + | T4_COMPRESSION_COLOUR); + t30_set_supported_bilevel_resolutions(t30, + T4_RESOLUTION_R8_STANDARD + | T4_RESOLUTION_R8_FINE + | T4_RESOLUTION_R8_SUPERFINE + | T4_RESOLUTION_R16_SUPERFINE + | T4_RESOLUTION_200_100 + | T4_RESOLUTION_200_200 + | T4_RESOLUTION_200_400 + | T4_RESOLUTION_300_300 + | T4_RESOLUTION_300_600 + | T4_RESOLUTION_400_400 + | T4_RESOLUTION_400_800 + | T4_RESOLUTION_600_600 + | T4_RESOLUTION_600_1200 + | T4_RESOLUTION_1200_1200); + t30_set_supported_colour_resolutions(t30, + T4_RESOLUTION_100_100 + | T4_RESOLUTION_200_200 + | T4_RESOLUTION_300_300 + | T4_RESOLUTION_400_400 + | T4_RESOLUTION_600_600 + | T4_RESOLUTION_1200_1200); logging = fax_get_logging_state(fax_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); diff --git a/libs/spandsp/tests/t42_tests.c b/libs/spandsp/tests/t42_tests.c index fe6b773e23..ea87b4eab3 100644 --- a/libs/spandsp/tests/t42_tests.c +++ b/libs/spandsp/tests/t42_tests.c @@ -300,7 +300,7 @@ int main(int argc, char *argv[]) memcpy(data, jpeg_table, jpeg_table_len - 2); if (total_len != total_image_len) - printf("Size mismatch %ld %ld\n", total_len, total_image_len); + printf("Size mismatch %ld %ld\n", (long int) total_len, (long int) total_image_len); off = total_len; switch (compression) { @@ -309,7 +309,7 @@ int main(int argc, char *argv[]) case COMPRESSION_CCITT_T6: break; case COMPRESSION_T85: - printf("T.85 image %ld bytes\n", total_len); + printf("T.85 image %ld bytes\n", (long int) total_len); for (i = 0; i < 16; i++) printf("0x%02x\n", data[i]); t85_decode_init(&t85_dec, t85_row_write_handler, NULL); @@ -322,7 +322,7 @@ int main(int argc, char *argv[]) t85_decode_release(&t85_dec); return 0; case COMPRESSION_T43: - printf("T.43 image %ld bytes\n", total_len); + printf("T.43 image %ld bytes\n", (long int) total_len); if (pack_16(data) == 0xFFA8) { data += 2; @@ -447,7 +447,7 @@ int main(int argc, char *argv[]) return 1; off += bytes_per_row; } - printf("total %u, off %ld\n", totdata, off); + printf("total %u, off %ld\n", totdata, (long int) off); /* We now have the image in memory in RGB form */ @@ -497,7 +497,7 @@ int main(int argc, char *argv[]) } TIFFClose(tif); - printf("XXX - image is %d by %d, %ld bytes\n", w, h, off); + printf("XXX - image is %d by %d, %ld bytes\n", w, h, (long int) off); /* We now have the image in memory in ITULAB form */ diff --git a/libs/spandsp/tests/t4_tests.c b/libs/spandsp/tests/t4_tests.c index 0af75b1ab5..98a57cfe54 100644 --- a/libs/spandsp/tests/t4_tests.c +++ b/libs/spandsp/tests/t4_tests.c @@ -288,20 +288,16 @@ int main(int argc, char *argv[]) compression_step = -1; } #endif -#if defined(SPANDSP_SUPPORT_T42) else if (strcmp(optarg, "T81") == 0) { compression = T4_COMPRESSION_T42_T81; compression_step = -1; } -#endif -#if defined(SPANDSP_SUPPORT_T43) else if (strcmp(optarg, "T43") == 0) { compression = T4_COMPRESSION_T43; compression_step = -1; } -#endif #if defined(SPANDSP_SUPPORT_T45) else if (strcmp(optarg, "T45") == 0) { diff --git a/libs/spandsp/yum-prepare.sh b/libs/spandsp/yum-prepare.sh new file mode 100644 index 0000000000..e41200482b --- /dev/null +++ b/libs/spandsp/yum-prepare.sh @@ -0,0 +1,26 @@ +: + +# +# Install the things which need adding to a fresh Fedora or Centos install to make it ready to build +# spandsp and its test suite +# +yum groupinstall "Development tools" +yum install fftw-devel \ + libtiff-tools \ + libtiff-devel \ + libjpeg-turbo-devel \ + libpcap-devel \ + libxml2-devel \ + libsndfile-devel \ + fltk-devel \ + fltk-fluid \ + libstdc++-devel \ + libstdc++-static \ + sox \ + gcc-c++ \ + libtool \ + autconf \ + automake \ + m4 \ + netpbm \ + netpbm-progs diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index 8f09145e71..be49b6c3e9 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -367,7 +367,7 @@ void stfu_n_reset(stfu_instance_t *i) i->last_rd_ts = 0; i->miss_count = 0; i->packet_count = 0; - + i->ts_offset = 0; } diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index dd83e7052d..fffd51abac 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -275,6 +275,7 @@ struct switch_runtime { char *core_db_post_trans_execute; char *core_db_inner_pre_trans_execute; char *core_db_inner_post_trans_execute; + int events_use_dispatch; }; extern struct switch_runtime runtime; diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 1a12da7129..8f02987281 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -65,6 +65,7 @@ typedef struct switch_thread_data_s { switch_thread_start_t func; void *obj; int alloc; + switch_memory_pool_t *pool; } switch_thread_data_t; typedef struct switch_hold_record_s { diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 006050bdc8..f90f1e190e 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1630,63 +1630,94 @@ typedef uint32_t switch_io_flag_t;
     SWITCH_EVENT_CUSTOM				- A custom event
+    SWITCH_EVENT_CLONE				- A cloned event
     SWITCH_EVENT_CHANNEL_CREATE		- A channel has been created
     SWITCH_EVENT_CHANNEL_DESTROY	- A channel has been destroyed
     SWITCH_EVENT_CHANNEL_STATE		- A channel has changed state
+    SWITCH_EVENT_CHANNEL_CALLSTATE	- A channel has changed call state
     SWITCH_EVENT_CHANNEL_ANSWER		- A channel has been answered
     SWITCH_EVENT_CHANNEL_HANGUP		- A channel has been hungup
+    SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE	- A channel has completed the hangup
     SWITCH_EVENT_CHANNEL_EXECUTE	- A channel has executed a module's application
     SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE	- A channel has finshed executing a module's application
-	SWITCH_EVENT_CHANNEL_BRIDGE     - A channel has bridged to another channel
-	SWITCH_EVENT_CHANNEL_UNBRIDGE   - A channel has unbridged from another channel
+    SWITCH_EVENT_CHANNEL_HOLD		- A channel has been put on hold
+    SWITCH_EVENT_CHANNEL_UNHOLD		- A channel has been unheld
+    SWITCH_EVENT_CHANNEL_BRIDGE     - A channel has bridged to another channel
+    SWITCH_EVENT_CHANNEL_UNBRIDGE   - A channel has unbridged from another channel
     SWITCH_EVENT_CHANNEL_PROGRESS	- A channel has started ringing
     SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA	- A channel has started early media
     SWITCH_EVENT_CHANNEL_OUTGOING	- A channel has been unparked
-	SWITCH_EVENT_CHANNEL_PARK 		- A channel has been parked
-	SWITCH_EVENT_CHANNEL_UNPARK 	- A channel has been unparked
-	SWITCH_EVENT_CHANNEL_APPLICATION- A channel has called and event from an application
-	SWITCH_EVENT_CHANNEL_ORIGINATE  - A channel has been originated
-	SWITCH_EVENT_CHANNEL_UUID       - A channel has changed uuid
+    SWITCH_EVENT_CHANNEL_PARK 		- A channel has been parked
+    SWITCH_EVENT_CHANNEL_UNPARK 	- A channel has been unparked
+    SWITCH_EVENT_CHANNEL_APPLICATION- A channel has called and event from an application
+    SWITCH_EVENT_CHANNEL_ORIGINATE  - A channel has been originated
+    SWITCH_EVENT_CHANNEL_UUID       - A channel has changed uuid
     SWITCH_EVENT_API				- An API call has been executed
     SWITCH_EVENT_LOG				- A LOG event has been triggered
     SWITCH_EVENT_INBOUND_CHAN		- A new inbound channel has been created
     SWITCH_EVENT_OUTBOUND_CHAN		- A new outbound channel has been created
     SWITCH_EVENT_STARTUP			- The system has been started
     SWITCH_EVENT_SHUTDOWN			- The system has been shutdown
-	SWITCH_EVENT_PUBLISH			- Publish
-	SWITCH_EVENT_UNPUBLISH			- UnPublish
-	SWITCH_EVENT_TALK				- Talking Detected
-	SWITCH_EVENT_NOTALK				- Not Talking Detected
-	SWITCH_EVENT_SESSION_CRASH		- Session Crashed
-	SWITCH_EVENT_MODULE_LOAD		- Module was loaded
-	SWITCH_EVENT_MODULE_UNLOAD		- Module was unloaded
-	SWITCH_EVENT_DTMF				- DTMF was sent
-	SWITCH_EVENT_MESSAGE			- A Basic Message
-	SWITCH_EVENT_PRESENCE_IN		- Presence in
-	SWITCH_EVENT_NOTIFY_IN			- Received incoming NOTIFY from gateway subscription
-	SWITCH_EVENT_PRESENCE_OUT		- Presence out
-	SWITCH_EVENT_PRESENCE_PROBE		- Presence probe
-	SWITCH_EVENT_MESSAGE_WAITING	- A message is waiting
-	SWITCH_EVENT_MESSAGE_QUERY		- A query for MESSAGE_WAITING events
-	SWITCH_EVENT_CODEC				- Codec Change
-	SWITCH_EVENT_BACKGROUND_JOB		- Background Job
-	SWITCH_EVENT_DETECTED_SPEECH	- Detected Speech
-	SWITCH_EVENT_DETECTED_TONE      - Detected Tone
-	SWITCH_EVENT_PRIVATE_COMMAND	- A private command event 
-	SWITCH_EVENT_HEARTBEAT			- Machine is alive
-	SWITCH_EVENT_TRAP				- Error Trap
-	SWITCH_EVENT_ADD_SCHEDULE		- Something has been scheduled
-	SWITCH_EVENT_DEL_SCHEDULE		- Something has been unscheduled
-	SWITCH_EVENT_EXE_SCHEDULE		- Something scheduled has been executed
-	SWITCH_EVENT_RE_SCHEDULE		- Something scheduled has been rescheduled
-	SWITCH_EVENT_RELOADXML			- XML registry has been reloaded
-	SWITCH_EVENT_NOTIFY				- Notification
-	SWITCH_EVENT_PHONE_FEATURE			- Notification (DND/CFWD/etc)
-	SWITCH_EVENT_PHONE_FEATURE_SUBSCRIBE - Phone feature subscription
-	SWITCH_EVENT_SEND_MESSAGE		- Message
-	SWITCH_EVENT_RECV_MESSAGE		- Message
-	SWITCH_EVENT_NAT            - NAT Management (new/del/status)
-	SWITCH_EVENT_FAILURE            - A failure occurred which might impact the normal functioning of the switch
+    SWITCH_EVENT_PUBLISH			- Publish
+    SWITCH_EVENT_UNPUBLISH			- UnPublish
+    SWITCH_EVENT_TALK				- Talking Detected
+    SWITCH_EVENT_NOTALK				- Not Talking Detected
+    SWITCH_EVENT_SESSION_CRASH		- Session Crashed
+    SWITCH_EVENT_MODULE_LOAD		- Module was loaded
+    SWITCH_EVENT_MODULE_UNLOAD		- Module was unloaded
+    SWITCH_EVENT_DTMF				- DTMF was sent
+    SWITCH_EVENT_MESSAGE			- A Basic Message
+    SWITCH_EVENT_PRESENCE_IN		- Presence in
+    SWITCH_EVENT_NOTIFY_IN			- Received incoming NOTIFY from gateway subscription
+    SWITCH_EVENT_PRESENCE_OUT		- Presence out
+    SWITCH_EVENT_PRESENCE_PROBE		- Presence probe
+    SWITCH_EVENT_MESSAGE_WAITING	- A message is waiting
+    SWITCH_EVENT_MESSAGE_QUERY		- A query for MESSAGE_WAITING events
+    SWITCH_EVENT_ROSTER				- ?
+    SWITCH_EVENT_CODEC				- Codec Change
+    SWITCH_EVENT_BACKGROUND_JOB		- Background Job
+    SWITCH_EVENT_DETECTED_SPEECH	- Detected Speech
+    SWITCH_EVENT_DETECTED_TONE      - Detected Tone
+    SWITCH_EVENT_PRIVATE_COMMAND	- A private command event 
+    SWITCH_EVENT_HEARTBEAT			- Machine is alive
+    SWITCH_EVENT_TRAP				- Error Trap
+    SWITCH_EVENT_ADD_SCHEDULE		- Something has been scheduled
+    SWITCH_EVENT_DEL_SCHEDULE		- Something has been unscheduled
+    SWITCH_EVENT_EXE_SCHEDULE		- Something scheduled has been executed
+    SWITCH_EVENT_RE_SCHEDULE		- Something scheduled has been rescheduled
+    SWITCH_EVENT_RELOADXML			- XML registry has been reloaded
+    SWITCH_EVENT_NOTIFY				- Notification
+    SWITCH_EVENT_PHONE_FEATURE		- Notification (DND/CFWD/etc)
+    SWITCH_EVENT_PHONE_FEATURE_SUBSCRIBE - Phone feature subscription
+    SWITCH_EVENT_SEND_MESSAGE		- Message
+    SWITCH_EVENT_RECV_MESSAGE		- Message
+    SWITCH_EVENT_REQUEST_PARAMS
+    SWITCH_EVENT_CHANNEL_DATA
+    SWITCH_EVENT_GENERAL
+    SWITCH_EVENT_COMMAND
+    SWITCH_EVENT_SESSION_HEARTBEAT
+    SWITCH_EVENT_CLIENT_DISCONNECTED
+    SWITCH_EVENT_SERVER_DISCONNECTED
+    SWITCH_EVENT_SEND_INFO
+    SWITCH_EVENT_RECV_INFO
+    SWITCH_EVENT_RECV_RTCP_MESSAGE
+    SWITCH_EVENT_CALL_SECURE
+    SWITCH_EVENT_NAT            	- NAT Management (new/del/status)
+    SWITCH_EVENT_RECORD_START
+    SWITCH_EVENT_RECORD_STOP
+    SWITCH_EVENT_PLAYBACK_START
+    SWITCH_EVENT_PLAYBACK_STOP
+    SWITCH_EVENT_CALL_UPDATE
+    SWITCH_EVENT_FAILURE            - A failure occurred which might impact the normal functioning of the switch
+    SWITCH_EVENT_SOCKET_DATA
+    SWITCH_EVENT_MEDIA_BUG_START
+    SWITCH_EVENT_MEDIA_BUG_STOP
+    SWITCH_EVENT_CONFERENCE_DATA_QUERY
+    SWITCH_EVENT_CONFERENCE_DATA
+    SWITCH_EVENT_CALL_SETUP_REQ
+    SWITCH_EVENT_CALL_SETUP_RESULT
+    SWITCH_EVENT_CALL_DETAIL
+    SWITCH_EVENT_DEVICE_STATE
     SWITCH_EVENT_ALL				- All events at once
 
diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index f4aa3d7f28..971a915bad 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -939,7 +939,7 @@ SWITCH_DECLARE(char *) switch_util_quote_shell_arg(const char *string); SWITCH_DECLARE(char *) switch_util_quote_shell_arg_pool(const char *string, switch_memory_pool_t *pool); -#define SWITCH_READ_ACCEPTABLE(status) (status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK) +#define SWITCH_READ_ACCEPTABLE(status) (status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK || status == SWITCH_STATUS_INUSE) SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len); SWITCH_DECLARE(char *) switch_url_decode(char *s); SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 0ad4c1bc67..6007fb2047 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -1459,6 +1459,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe if (switch_channel_test_flag(channel, CF_VIDEO)) { if (switch_test_flag(conference, CFLAG_VIDEO_BRIDGE)) { switch_channel_set_flag(channel, CF_VIDEO_ECHO); + switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE); } else { switch_channel_clear_flag(channel, CF_VIDEO_ECHO); } @@ -1618,7 +1619,7 @@ static void conference_set_video_floor_holder(conference_obj_t *conference, conf if (member) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Adding video floor %s\n", switch_channel_get_name(member->channel)); - switch_channel_set_flag(member->channel, CF_VIDEO_PASSIVE); + //switch_channel_set_flag(member->channel, CF_VIDEO_PASSIVE); switch_core_session_refresh_video(member->session); conference->video_floor_holder = member; } else { @@ -1627,7 +1628,7 @@ static void conference_set_video_floor_holder(conference_obj_t *conference, conf if (old_member) { old_id = old_member->id; - switch_channel_clear_flag(old_member->channel, CF_VIDEO_PASSIVE); + //switch_channel_clear_flag(old_member->channel, CF_VIDEO_PASSIVE); } switch_set_flag(conference, CFLAG_FLOOR_CHANGE); @@ -7488,6 +7489,7 @@ SWITCH_STANDARD_APP(conference_function) switch_core_session_video_reset(session); switch_channel_set_flag(channel, CF_CONFERENCE); + switch_channel_set_flag(channel, CF_VIDEO_PASSIVE); if (switch_channel_answer(channel) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Channel answer failed.\n"); @@ -8042,6 +8044,7 @@ SWITCH_STANDARD_APP(conference_function) end: switch_channel_clear_flag(channel, CF_CONFERENCE); + switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE); switch_core_session_video_reset(session); } diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index d2cefcfea4..d795e8e48b 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1689,6 +1689,9 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj) switch_channel_set_state(channel, CS_EXECUTE); switch_core_session_rwunlock(session); + sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1 where uuid='%q' and ring_count > 0", h->uuid); + fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); + end: switch_event_destroy(&ovars); diff --git a/src/mod/applications/mod_http_cache/conf/autoload_configs/http_cache.conf.xml b/src/mod/applications/mod_http_cache/conf/autoload_configs/http_cache.conf.xml index cdbe40d100..ce68ea09b0 100644 --- a/src/mod/applications/mod_http_cache/conf/autoload_configs/http_cache.conf.xml +++ b/src/mod/applications/mod_http_cache/conf/autoload_configs/http_cache.conf.xml @@ -12,15 +12,18 @@ - - - + + + + + + diff --git a/src/mod/applications/mod_http_cache/mod_http_cache.c b/src/mod/applications/mod_http_cache/mod_http_cache.c index 10882857fc..24ea2aa76c 100644 --- a/src/mod/applications/mod_http_cache/mod_http_cache.c +++ b/src/mod/applications/mod_http_cache/mod_http_cache.c @@ -36,6 +36,9 @@ #include #include "aws.h" +/* 253 max domain size + '/' + NUL byte */ +#define DOMAIN_BUF_SIZE 255 + /* Defines module interface to FreeSWITCH */ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_http_cache_shutdown); SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load); @@ -151,6 +154,8 @@ struct url_cache { char *location; /** HTTP profiles */ switch_hash_t *profiles; + /** profiles mapped by FQDN */ + switch_hash_t *fqdn_profiles; /** Cache mapped by URL */ switch_hash_t *map; /** Cached URLs queued for replacement */ @@ -195,10 +200,41 @@ static void url_cache_lock(url_cache_t *cache, switch_core_session_t *session); static void url_cache_unlock(url_cache_t *cache, switch_core_session_t *session); static void url_cache_clear(url_cache_t *cache, switch_core_session_t *session); static http_profile_t *url_cache_http_profile_find(url_cache_t *cache, const char *name); -static void url_cache_http_profile_add(url_cache_t *cache, const char *name, const char *aws_s3_access_key_id, const char *aws_s3_secret_access_key); +static http_profile_t *url_cache_http_profile_find_by_fqdn(url_cache_t *cache, const char *url); +static http_profile_t *url_cache_http_profile_add(url_cache_t *cache, const char *name, const char *aws_s3_access_key_id, const char *aws_s3_secret_access_key); static switch_curl_slist_t *append_aws_s3_headers(switch_curl_slist_t *headers, http_profile_t *profile, const char *verb, const char *content_type, const char *url); + +/** + * Parse FQDN from URL + */ +static void parse_domain(const char *url, char *domain_buf, int domain_buf_len) +{ + char *end; + char *start; + domain_buf[0] = '\0'; + if (zstr(url)) { + return; + } + start = strstr(url, "://"); + if (!start) { + return; + } + start += 3; + if (!*start) { + return; + } + strncpy(domain_buf, start, domain_buf_len); + end = strchr(domain_buf, '/'); + if (end) { + *end = '\0'; + } else { + /* bad URL */ + domain_buf[0] = '\0'; + } +} + /** * Put a file to the URL * @param cache the cache @@ -233,6 +269,12 @@ static switch_status_t http_put(url_cache_t *cache, http_profile_t *profile, swi } buf = switch_mprintf("Content-Type: %s", mime_type); + + /* find profile for domain */ + if (!profile) { + profile = url_cache_http_profile_find_by_fqdn(cache, url); + } + headers = switch_curl_slist_append(headers, buf); headers = append_aws_s3_headers(headers, profile, "PUT", mime_type, url); @@ -732,10 +774,25 @@ static http_profile_t *url_cache_http_profile_find(url_cache_t *cache, const cha return NULL; } +/** + * Find a profile by domain name + */ +static http_profile_t *url_cache_http_profile_find_by_fqdn(url_cache_t *cache, const char *url) +{ + if (cache && !zstr(url)) { + char fqdn[DOMAIN_BUF_SIZE]; + parse_domain(url, fqdn, DOMAIN_BUF_SIZE); + if (!zstr_buf(fqdn)) { + return (http_profile_t *)switch_core_hash_find(cache->fqdn_profiles, fqdn); + } + } + return NULL; +} + /** * Add a profile to the cache */ -static void url_cache_http_profile_add(url_cache_t *cache, const char *name, const char *aws_s3_access_key_id, const char *aws_s3_secret_access_key) +static http_profile_t *url_cache_http_profile_add(url_cache_t *cache, const char *name, const char *aws_s3_access_key_id, const char *aws_s3_secret_access_key) { http_profile_t *profile = switch_core_alloc(cache->pool, sizeof(*profile)); profile->name = switch_core_strdup(cache->pool, name); @@ -746,6 +803,7 @@ static void url_cache_http_profile_add(url_cache_t *cache, const char *name, con profile->aws_s3_secret_access_key = switch_core_strdup(cache->pool, aws_s3_secret_access_key); } switch_core_hash_insert(cache->profiles, profile->name, profile); + return profile; } /** @@ -901,6 +959,11 @@ static switch_status_t http_get(url_cache_t *cache, http_profile_t *profile, cac get_data.fd = 0; get_data.url = url; + /* find profile for domain */ + if (!profile) { + profile = url_cache_http_profile_find_by_fqdn(cache, url->url); + } + /* add optional AWS S3 headers if necessary */ headers = append_aws_s3_headers(headers, profile, "GET", "", url->url); @@ -1329,6 +1392,8 @@ static switch_status_t do_config(url_cache_t *cache) for (profile = switch_xml_child(profiles, "profile"); profile; profile = profile->next) { const char *name = switch_xml_attr_soft(profile, "name"); if (!zstr(name)) { + http_profile_t *profile_obj; + switch_xml_t domains; switch_xml_t s3 = switch_xml_child(profile, "aws-s3"); const char *access_key_id = NULL; const char *secret_access_key = NULL; @@ -1348,7 +1413,21 @@ static switch_status_t do_config(url_cache_t *cache) } } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding profile \"%s\" to cache\n", name); - url_cache_http_profile_add(cache, name, access_key_id, secret_access_key); + profile_obj = url_cache_http_profile_add(cache, name, access_key_id, secret_access_key); + + domains = switch_xml_child(profile, "domains"); + if (domains) { + switch_xml_t domain; + for (domain = switch_xml_child(domains, "domain"); domain; domain = domain->next) { + const char *fqdn = switch_xml_attr_soft(domain, "name"); + if (!zstr(fqdn)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding profile \"%s\" domain \"%s\" to cache\n", name, fqdn); + switch_core_hash_insert(cache->fqdn_profiles, fqdn, profile_obj); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "HTTP profile domain missing name!\n"); + } + } + } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "HTTP profile missing name\n"); } @@ -1554,6 +1633,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load) gcache.pool = pool; switch_core_hash_init(&gcache.map, gcache.pool); switch_core_hash_init(&gcache.profiles, gcache.pool); + switch_core_hash_init_nocase(&gcache.fqdn_profiles, gcache.pool); switch_mutex_init(&gcache.mutex, SWITCH_MUTEX_UNNESTED, gcache.pool); switch_thread_rwlock_create(&gcache.shutdown_lock, gcache.pool); @@ -1626,6 +1706,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_http_cache_shutdown) url_cache_clear(&gcache, NULL); switch_core_hash_destroy(&gcache.map); switch_core_hash_destroy(&gcache.profiles); + switch_core_hash_destroy(&gcache.fqdn_profiles); switch_mutex_destroy(gcache.mutex); return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp index 6af6a0075e..a52b8a1ac4 100644 --- a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp +++ b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp @@ -1658,16 +1658,35 @@ int gsmopen_serial_read_AT(private_t *tech_pvt, int look_for_ack, int timeout_us char content2[1000]; SMSMessageRef sms; + DEBUGA_GSMOPEN("about to decode\n", GSMOPEN_P_LOG); try { sms = SMSMessage::decode(tech_pvt->line_array.result[i]); // dataCodingScheme = 8 , text=ciao 123 belè новости לק ראת ﺎﻠﺠﻤﻋﺓ 人大 } catch(...) { ERRORA("GsmException\n", GSMOPEN_P_LOG); + gsmopen_sleep(5000); return -1; } - DEBUGA_GSMOPEN("SMS=\n%s\n", GSMOPEN_P_LOG, sms->toString().c_str()); + DEBUGA_GSMOPEN("after decode\n", GSMOPEN_P_LOG); +#if 0 + char letsee[1024]; + memset(letsee, '\0', sizeof(letsee)); + + DEBUGA_GSMOPEN("about to letsee\n", GSMOPEN_P_LOG); + try { + sprintf(letsee, "|%s|\n", sms->toString().c_str()); + } + catch(...) { + ERRORA("GsmException\n", GSMOPEN_P_LOG); + sleep(5); + return -1; + } + DEBUGA_GSMOPEN("after letsee\n", GSMOPEN_P_LOG); + + DEBUGA_GSMOPEN("SMS=\n%s\n", GSMOPEN_P_LOG, letsee); +#endif //0 memset(content2, '\0', sizeof(content2)); if (sms->dataCodingScheme().getAlphabet() == DCS_DEFAULT_ALPHABET) { iso_8859_1_to_utf8(tech_pvt, (char *) sms->userData().c_str(), content2, sizeof(content2)); @@ -1701,6 +1720,7 @@ int gsmopen_serial_read_AT(private_t *tech_pvt, int look_for_ack, int timeout_us } catch(...) { ERRORA("GsmException\n", GSMOPEN_P_LOG); + gsmopen_sleep(5000); return -1; } diff --git a/src/mod/endpoints/mod_rtmp/mod_rtmp.c b/src/mod/endpoints/mod_rtmp/mod_rtmp.c index 113036dafb..339ce81873 100644 --- a/src/mod/endpoints/mod_rtmp/mod_rtmp.c +++ b/src/mod/endpoints/mod_rtmp/mod_rtmp.c @@ -250,7 +250,6 @@ switch_status_t rtmp_on_hangup(switch_core_session_t *session) rtmp_private_t *tech_pvt = NULL; rtmp_session_t *rsession = NULL; - switch_core_session_write_lock(session); channel = switch_core_session_get_channel(session); assert(channel != NULL); @@ -311,7 +310,6 @@ switch_status_t rtmp_on_hangup(switch_core_session_t *session) switch_thread_rwlock_unlock(rsession->rwlock); done: - switch_core_session_rwunlock(session); return SWITCH_STATUS_SUCCESS; } @@ -851,15 +849,13 @@ switch_status_t rtmp_session_destroy(rtmp_session_t **rsession) /* At this point we don't know if the session still exists, so request a fresh pointer to it from the core. */ if ( (session = switch_core_session_locate((char *)key)) != NULL ) { - switch_core_session_rwunlock(session); - /* * This is here so that if the FS session still exists and has the FS session write(or read) lock, then we won't destroy the rsession * until the FS session is finished with it. But if the rsession is able to get the FS session * write lock, before the FS session is hungup, then once the FS session does get the write lock * the rsession pointer will be null, and the FS session will never try and touch the already destroyed rsession. */ - switch_core_session_write_lock(session); + channel = switch_core_session_get_channel(session); tech_pvt = switch_core_session_get_private(session); if ( tech_pvt && tech_pvt->rtmp_session ) { diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index 13a94810f8..e329affb5c 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -757,10 +757,73 @@ switch_status_t channel_on_routing(switch_core_session_t *session) return SWITCH_STATUS_SUCCESS; } +struct channel_on_execute_helper { + private_t *tech_pvt; + listener_t *listener; + uint32_t line_instance; +}; + +int channel_on_execute_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + struct channel_on_routing_helper *helper = pArg; + listener_t *listener = NULL; + + char *device_name = argv[0]; + uint32_t device_instance = atoi(argv[1]); + /* uint32_t position = atoi(argv[2]); */ + uint32_t line_instance = atoi(argv[3]); + /* char *label = argv[4]; */ + /* char *value = argv[5]; */ + /* char *caller_name = argv[6]; */ + /* uint32_t ring_on_idle = atoi(argv[7]); */ + /* uint32_t ring_on_active = atoi(argv[8]); */ + /* uint32_t busy_trigger = atoi(argv[9]); */ + /* char *forward_all = argv[10]; */ + /* char *forward_busy = argv[11]; */ + /* char *forward_noanswer = argv[12]; */ + /* uint32_t noanswer_duration = atoi(argv[13]); */ + /* char *channel_uuid = argv[14]; */ + /* uint32_t call_id = atoi(argv[15]); */ + /* uint32_t call_state = atoi(argv[16]); */ + + skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, device_name, device_instance, &listener); + if(listener) { + if(!strcmp(device_name, helper->listener->device_name) + && (device_instance == helper->listener->device_instance) + && (line_instance == helper->line_instance)) {/* the calling line */ + helper->tech_pvt->caller_profile->dialplan = switch_core_strdup(helper->tech_pvt->caller_profile->pool, listener->profile->dialplan); + helper->tech_pvt->caller_profile->context = switch_core_strdup(helper->tech_pvt->caller_profile->pool, listener->profile->context); + + send_stop_tone(listener, line_instance, helper->tech_pvt->call_id); + } else { + } + } + return 0; +} + switch_status_t channel_on_execute(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { + private_t *tech_pvt = switch_core_session_get_private(session); + listener_t *listener = NULL; + struct channel_on_execute_helper helper = {0}; + + skinny_profile_find_listener_by_device_name_and_instance(tech_pvt->profile, + switch_channel_get_variable(channel, "skinny_device_name"), + atoi(switch_channel_get_variable(channel, "skinny_device_instance")), &listener); + if (listener) { + helper.tech_pvt = tech_pvt; + helper.listener = listener; + helper.line_instance = atoi(switch_channel_get_variable(channel, "skinny_line_instance")); + skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), channel_on_execute_callback, &helper); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Could not find listener %s:%s for Channel %s\n", + switch_channel_get_variable(channel, "skinny_device_name"), switch_channel_get_variable(channel, "skinny_device_instance"), + switch_channel_get_name(channel)); + } + } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel)); return SWITCH_STATUS_SUCCESS; diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index e3ffae4778..8efb07193f 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -2716,8 +2716,12 @@ static void xml_gateway_status(sofia_gateway_t *gp, switch_stream_handle_t *stre stream->write_function(stream, " %d\n", gp->freq); stream->write_function(stream, " %d\n", gp->ping); stream->write_function(stream, " %d\n", gp->ping_freq); + stream->write_function(stream, " %d\n", gp->ping_min); + stream->write_function(stream, " %d\n", gp->ping_count); + stream->write_function(stream, " %d\n", gp->ping_max); + stream->write_function(stream, " %d\n", gp->pinging); stream->write_function(stream, " %s\n", sofia_state_names[gp->state]); - stream->write_function(stream, " %s%s\n", status_names[gp->status], gp->pinging ? " (ping)" : ""); + stream->write_function(stream, " %s\n", status_names[gp->status]); stream->write_function(stream, " %u\n", gp->ib_calls); stream->write_function(stream, " %u\n", gp->ob_calls); stream->write_function(stream, " %u\n", gp->ib_failed_calls); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index c0fb9e720e..f91c81abc5 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -8525,6 +8525,7 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia call_info = call_info->ci_next; } + call_info = sip_call_info(sip); } else if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) { char buf[128] = ""; @@ -8694,6 +8695,8 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia profile_dup_clean(dialplan, tech_pvt->caller_profile->dialplan, tech_pvt->caller_profile->pool); profile_dup_clean(displayname, tech_pvt->caller_profile->caller_id_name, tech_pvt->caller_profile->pool); profile_dup_clean(from_user, tech_pvt->caller_profile->caller_id_number, tech_pvt->caller_profile->pool); + profile_dup_clean(displayname, tech_pvt->caller_profile->orig_caller_id_name, tech_pvt->caller_profile->pool); + profile_dup_clean(from_user, tech_pvt->caller_profile->orig_caller_id_number, tech_pvt->caller_profile->pool); profile_dup_clean(network_ip, tech_pvt->caller_profile->network_addr, tech_pvt->caller_profile->pool); profile_dup_clean(from_user, tech_pvt->caller_profile->ani, tech_pvt->caller_profile->pool); profile_dup_clean(aniii, tech_pvt->caller_profile->aniii, tech_pvt->caller_profile->pool); @@ -8716,14 +8719,21 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia if ((b_session = switch_core_session_locate(b_private->uuid))) { switch_channel_t *b_channel = switch_core_session_get_channel(b_session); const char *bridge_uuid; - switch_caller_profile_t *orig_cp; + switch_caller_profile_t *orig_cp, *cp; //const char *sent_name, *sent_number; orig_cp = switch_channel_get_caller_profile(b_channel); tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_name); tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_number); - tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name); - tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number); + if (!call_info) { + tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name); + tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number); + } + + if (orig_cp) { + cp = switch_caller_profile_dup(tech_pvt->caller_profile->pool, orig_cp); + switch_channel_set_originator_caller_profile(channel, cp); + } #if 0 sent_name = switch_channel_get_variable(b_channel, "last_sent_callee_id_name"); @@ -8775,19 +8785,37 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "%sanswer,intercept:%s", codec_str, bridge_uuid); } else { - const char *name = NULL, *num = NULL; switch_caller_profile_t *bcp = switch_channel_get_caller_profile(b_channel); - if (switch_channel_test_flag(b_channel, CF_BRIDGE_ORIGINATOR) || !switch_channel_test_flag(b_channel, CF_BRIDGED)) { - name = bcp->callee_id_name; - num = bcp->callee_id_number; - } else { - name = bcp->caller_id_name; - num = bcp->caller_id_number; + if (switch_channel_test_flag(b_channel, CF_BRIDGE_ORIGINATOR)) { + switch_channel_set_flag(tech_pvt->channel, CF_BRIDGE_ORIGINATOR); } - tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, name); - tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, num); + if (!zstr(bcp->callee_id_name)) { + tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->callee_id_name); + } + + if (!zstr(bcp->callee_id_number)) { + tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->callee_id_number); + } + + + if (!zstr(bcp->caller_id_name)) { + tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->caller_id_name); + } + + if (!zstr(bcp->caller_id_number)) { + tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->caller_id_number); + } + + if (bcp->originatee_caller_profile) { + switch_caller_profile_t *cp; + + cp = switch_caller_profile_dup(tech_pvt->caller_profile->pool, + bcp->originatee_caller_profile); + + switch_channel_set_originatee_caller_profile(tech_pvt->channel, cp); + } tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "%sanswer,sofia_sla:%s", codec_str, b_private->uuid); diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 465455568b..17a85a94c8 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -1346,18 +1346,18 @@ static switch_event_t *actual_sofia_presence_event_handler(switch_event_t *event "((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') order by rcd desc", uuid, mod_sofia_globals.hostname, profile->name, euser, host, euser, host); } - + + sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_dialog_callback, &dh); + if (mod_sofia_globals.debug_presence > 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "CHECK SQL: %s@%s [%s]\nhits: %d\n", euser, host, sql, dh.hits); } - sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_dialog_callback, &dh); - - switch_safe_free(sql); -#if 0 + if (hup && dh.hits > 0) { /* sigh, mangle this packet to simulate a call that is up instead of hungup */ + hup = 0; event->flags |= EF_UNIQ_HEADERS; if (!strcasecmp(dh.state, "early")) { @@ -1386,7 +1386,7 @@ static switch_event_t *actual_sofia_presence_event_handler(switch_event_t *event switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "confirmed"); } } -#endif + if (zstr(call_id) && (dh.hits && presence_source && (!strcasecmp(presence_source, "register") || switch_stristr("register", status)))) { @@ -2553,7 +2553,8 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * char *open_closed = NULL; char *dialog_status = NULL; char *dialog_rpid = NULL; - char *default_dialog = "partial"; + //char *default_dialog = "partial"; + char *default_dialog = "full"; const char *ct = "no/idea"; char *to = NULL; @@ -2731,9 +2732,9 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * } - if (user_agent && switch_stristr("snom", user_agent) && uuid) { - default_dialog = "full" ; - } + //if (user_agent && switch_stristr("snom", user_agent) && uuid) { + // default_dialog = "full" ; + //} if (call_state && !strcasecmp(call_state, "cs_hangup")) { astate = "hangup"; diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index b6505773f1..e79013befe 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -1737,7 +1737,7 @@ SWITCH_STANDARD_API(erlang_cmd) stream->write_function(stream, "directory\n"); } else if (ptr->section == SWITCH_XML_SECTION_DIALPLAN) { stream->write_function(stream, "dialplan\n"); - } else if (ptr->section == SWITCH_XML_SECTION_PHRASES) { + } else if (ptr->section == SWITCH_XML_SECTION_LANGUAGES) { stream->write_function(stream, "phrases\n"); } else if (ptr->section == SWITCH_XML_SECTION_CHATPLAN) { stream->write_function(stream, "chatplan\n"); diff --git a/src/mod/event_handlers/mod_rayo/nlsml.c b/src/mod/event_handlers/mod_rayo/nlsml.c index b5e9cefa4f..b050565071 100644 --- a/src/mod/event_handlers/mod_rayo/nlsml.c +++ b/src/mod/event_handlers/mod_rayo/nlsml.c @@ -397,9 +397,10 @@ static int isdtmf(const char digit) /** * Construct an NLSML result for digit match * @param digits the matching digits + * @param interpretation the optional digit interpretation * @return the NLSML */ -iks *nlsml_create_dtmf_match(const char *digits) +iks *nlsml_create_dtmf_match(const char *digits, const char *interpretation) { iks *result = iks_new("result"); iks_insert_attrib(result, "xmlns", NLSML_NS); @@ -410,10 +411,11 @@ iks *nlsml_create_dtmf_match(const char *digits) int num_digits = strlen(digits); switch_stream_handle_t stream = { 0 }; - iks *interpretation = iks_insert(result, "interpretation"); - iks *input = iks_insert(interpretation, "input"); - iks_insert_attrib(input, "mode", "dtmf"); - iks_insert_attrib(input, "confidence", "100"); + iks *interpretation_node = iks_insert(result, "interpretation"); + iks *input_node = iks_insert(interpretation_node, "input"); + iks *instance_node = iks_insert(interpretation_node, "instance"); + iks_insert_attrib(input_node, "mode", "dtmf"); + iks_insert_attrib(input_node, "confidence", "100"); SWITCH_STANDARD_STREAM(stream); for (i = 0; i < num_digits; i++) { @@ -426,7 +428,13 @@ iks *nlsml_create_dtmf_match(const char *digits) } } } - iks_insert_cdata(input, stream.data, strlen(stream.data)); + iks_insert_cdata(input_node, stream.data, strlen(stream.data)); + + if (zstr(interpretation)) { + iks_insert_cdata(instance_node, stream.data, strlen(stream.data)); + } else { + iks_insert_cdata(instance_node, interpretation, strlen(interpretation)); + } switch_safe_free(stream.data); } return result; diff --git a/src/mod/event_handlers/mod_rayo/nlsml.h b/src/mod/event_handlers/mod_rayo/nlsml.h index d8417213ec..75c4ad6378 100644 --- a/src/mod/event_handlers/mod_rayo/nlsml.h +++ b/src/mod/event_handlers/mod_rayo/nlsml.h @@ -42,7 +42,7 @@ enum nlsml_match_type { extern int nlsml_init(void); enum nlsml_match_type nlsml_parse(const char *result, const char *uuid); iks *nlsml_normalize(const char *result); -extern iks *nlsml_create_dtmf_match(const char *digits); +extern iks *nlsml_create_dtmf_match(const char *digits, const char *interpretation); #endif diff --git a/src/mod/event_handlers/mod_rayo/rayo_input_component.c b/src/mod/event_handlers/mod_rayo/rayo_input_component.c index 3bf3b6dfb6..8238deb48a 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_input_component.c +++ b/src/mod/event_handlers/mod_rayo/rayo_input_component.c @@ -157,6 +157,7 @@ static switch_status_t input_component_on_dtmf(switch_core_session_t *session, c int is_term_digit = 0; struct input_component *component; enum srgs_match_type match; + const char *interpretation = NULL; switch_mutex_lock(handler->mutex); @@ -179,7 +180,7 @@ static switch_status_t input_component_on_dtmf(switch_core_session_t *session, c switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Collected term digit = \"%c\"\n", dtmf->digit); } - match = srgs_grammar_match(component->grammar, component->digits); + match = srgs_grammar_match(component->grammar, component->digits, &interpretation); /* adjust result if terminating digit was pressed */ if (is_term_digit) { @@ -208,7 +209,7 @@ static switch_status_t input_component_on_dtmf(switch_core_session_t *session, c break; } case SMT_MATCH_END: { - iks *result = nlsml_create_dtmf_match(component->digits); + iks *result = nlsml_create_dtmf_match(component->digits, interpretation); /* notify of match and remove input component */ handler->dtmf_component = NULL; switch_core_media_bug_remove(session, &handler->bug); @@ -248,13 +249,14 @@ static switch_bool_t input_component_bug_callback(switch_media_bug_t *bug, void int elapsed_ms = (switch_micro_time_now() - component->last_digit_time) / 1000; if (component->num_digits && component->inter_digit_timeout > 0 && elapsed_ms > component->inter_digit_timeout) { enum srgs_match_type match; + const char *interpretation = NULL; handler->dtmf_component = NULL; switch_core_media_bug_set_flag(bug, SMBF_PRUNE); /* we got some input, check for match */ - match = srgs_grammar_match(component->grammar, component->digits); + match = srgs_grammar_match(component->grammar, component->digits, &interpretation); if (match == SMT_MATCH || match == SMT_MATCH_END) { - iks *result = nlsml_create_dtmf_match(component->digits); + iks *result = nlsml_create_dtmf_match(component->digits, interpretation); /* notify of match */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "MATCH = %s\n", component->digits); send_match_event(RAYO_COMPONENT(component), result); diff --git a/src/mod/event_handlers/mod_rayo/srgs.c b/src/mod/event_handlers/mod_rayo/srgs.c index 1d5ce0e08e..86cf825635 100644 --- a/src/mod/event_handlers/mod_rayo/srgs.c +++ b/src/mod/event_handlers/mod_rayo/srgs.c @@ -33,6 +33,7 @@ #include "srgs.h" #define MAX_RECURSION 100 +#define MAX_TAGS 30 /** function to handle tag attributes */ typedef int (* tag_attribs_fn)(struct srgs_grammar *, char **); @@ -111,6 +112,7 @@ struct item_value { int repeat_min; int repeat_max; const char *weight; + int tag; }; /** @@ -161,6 +163,10 @@ struct srgs_grammar { struct srgs_node *cur; /** rule names mapped to node */ switch_hash_t *rules; + /** possible matching tags */ + const char *tags[MAX_TAGS + 1]; + /** number of tags */ + int tag_count; /** grammar encoding */ char *encoding; /** grammar language */ @@ -708,6 +714,32 @@ static int tag_hook(void *user_data, char *name, char **atts, int type) return result; } +/** + * Process CDATA + * @param grammar the grammar + * @param data the CDATA + * @param len the CDATA length + * @return IKS_OK + */ +static int process_cdata_tag(struct srgs_grammar *grammar, char *data, size_t len) +{ + struct srgs_node *item = grammar->cur->parent; + if (item && item->type == SNT_ITEM) { + if (grammar->tag_count < MAX_TAGS) { + /* grammar gets the tag name, item gets the unique tag number */ + char *tag = switch_core_alloc(grammar->pool, sizeof(char) * (len + 1)); + tag[len] = '\0'; + strncpy(tag, data, len); + grammar->tags[++grammar->tag_count] = tag; + item->value.item.tag = grammar->tag_count; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "too many s\n"); + return IKS_BADXML; + } + } + return IKS_OK; +} + /** * Process CDATA grammar tokens * @param grammar the grammar @@ -956,8 +988,12 @@ static int create_regexes(struct srgs_grammar *grammar, struct srgs_node *node, case SNT_ITEM: if (node->child) { struct srgs_node *item = node->child; - if (node->value.item.repeat_min != 1 || node->value.item.repeat_max != 1) { - stream->write_function(stream, "%s", "(?:"); + if (node->value.item.repeat_min != 1 || node->value.item.repeat_max != 1 || node->value.item.tag) { + if (node->value.item.tag) { + stream->write_function(stream, "(?P<%d>", node->value.item.tag); + } else { + stream->write_function(stream, "%s", "(?:"); + } } for(; item; item = item->next) { if (!create_regexes(grammar, item, stream)) { @@ -980,6 +1016,8 @@ static int create_regexes(struct srgs_grammar *grammar, struct srgs_node *node, } else { stream->write_function(stream, "){%i}", node->value.item.repeat_min); } + } else if (node->value.item.tag) { + stream->write_function(stream, "%s", ")"); } } break; @@ -1171,7 +1209,7 @@ struct srgs_grammar *srgs_parse(struct srgs_parser *parser, const char *document } #define MAX_INPUT_SIZE 128 -#define OVECTOR_SIZE 30 +#define OVECTOR_SIZE MAX_TAGS #define WORKSPACE_SIZE 1024 /** @@ -1214,15 +1252,17 @@ static int is_match_end(pcre *compiled_regex, const char *input) * Find a match * @param grammar the grammar to match * @param input the input to compare + * @param interpretation the (optional) interpretation of the input result * @return the match result */ -enum srgs_match_type srgs_grammar_match(struct srgs_grammar *grammar, const char *input) +enum srgs_match_type srgs_grammar_match(struct srgs_grammar *grammar, const char *input, const char **interpretation) { int result = 0; int ovector[OVECTOR_SIZE]; - int workspace[WORKSPACE_SIZE]; pcre *compiled_regex; + *interpretation = NULL; + if (zstr(input)) { return SMT_NO_MATCH; } @@ -1234,12 +1274,26 @@ enum srgs_match_type srgs_grammar_match(struct srgs_grammar *grammar, const char if (!(compiled_regex = get_compiled_regex(grammar))) { return SMT_NO_MATCH; } - result = pcre_dfa_exec(compiled_regex, NULL, input, strlen(input), 0, PCRE_PARTIAL, - ovector, sizeof(ovector) / sizeof(ovector[0]), - workspace, sizeof(workspace) / sizeof(workspace[0])); + result = pcre_exec(compiled_regex, NULL, input, strlen(input), 0, PCRE_PARTIAL, + ovector, OVECTOR_SIZE); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "match = %i\n", result); if (result > 0) { + int i; + char buffer[MAX_INPUT_SIZE + 1]; + buffer[MAX_INPUT_SIZE] = '\0'; + + /* find matching instance... */ + for (i = 1; i <= grammar->tag_count; i++) { + char substring_name[16] = { 0 }; + buffer[0] = '\0'; + snprintf(substring_name, 16, "%d", i); + if (pcre_copy_named_substring(compiled_regex, input, ovector, result, substring_name, buffer, MAX_INPUT_SIZE) != PCRE_ERROR_NOSUBSTRING && !zstr_buf(buffer)) { + *interpretation = grammar->tags[i]; + break; + } + } + if (is_match_end(compiled_regex, input)) { return SMT_MATCH_END; } @@ -1562,7 +1616,7 @@ int srgs_init(void) add_root_tag_def("grammar", process_grammar, process_cdata_bad, "meta,metadata,lexicon,tag,rule"); add_tag_def("ruleref", process_ruleref, process_cdata_bad, ""); add_tag_def("token", process_attribs_ignore, process_cdata_ignore, ""); - add_tag_def("tag", process_attribs_ignore, process_cdata_ignore, ""); + add_tag_def("tag", process_attribs_ignore, process_cdata_tag, ""); add_tag_def("one-of", process_attribs_ignore, process_cdata_tokens, "item"); add_tag_def("item", process_item, process_cdata_tokens, "token,ruleref,item,one-of,tag"); add_tag_def("rule", process_rule, process_cdata_tokens, "token,ruleref,item,one-of,tag,example"); diff --git a/src/mod/event_handlers/mod_rayo/srgs.h b/src/mod/event_handlers/mod_rayo/srgs.h index f777c9f523..29ee916ce7 100644 --- a/src/mod/event_handlers/mod_rayo/srgs.h +++ b/src/mod/event_handlers/mod_rayo/srgs.h @@ -51,7 +51,7 @@ extern struct srgs_grammar *srgs_parse(struct srgs_parser *parser, const char *d extern const char *srgs_grammar_to_regex(struct srgs_grammar *grammar); extern const char *srgs_grammar_to_jsgf(struct srgs_grammar *grammar); extern const char *srgs_grammar_to_jsgf_file(struct srgs_grammar *grammar, const char *basedir, const char *ext); -extern enum srgs_match_type srgs_grammar_match(struct srgs_grammar *grammar, const char *input); +extern enum srgs_match_type srgs_grammar_match(struct srgs_grammar *grammar, const char *input, const char **interpretation); extern void srgs_parser_destroy(struct srgs_parser *parser); #endif diff --git a/src/mod/event_handlers/mod_rayo/test_nlsml/main.c b/src/mod/event_handlers/mod_rayo/test_nlsml/main.c index f5d6067d3b..0577288b7c 100644 --- a/src/mod/event_handlers/mod_rayo/test_nlsml/main.c +++ b/src/mod/event_handlers/mod_rayo/test_nlsml/main.c @@ -245,14 +245,15 @@ static const char *nlsml_dtmf_result = "" "1 2 3 4" + "1 2 3 4" ""; /** - * Test parsing NLSML example results + * Test creating DTMF match result */ static void test_create_dtmf_match(void) { - iks *result = nlsml_create_dtmf_match("1234"); + iks *result = nlsml_create_dtmf_match("1234", NULL); char *result_str; ASSERT_NOT_NULL(result); result_str = iks_string(NULL, result); @@ -260,6 +261,26 @@ static void test_create_dtmf_match(void) iks_free(result_str); } +static const char *nlsml_dtmf_instance_result = + "" + "1" + "foo" + ""; + +/** + * Test creating DTMF match result with instance interpretation + */ +static void test_create_dtmf_instance(void) +{ + iks *result = nlsml_create_dtmf_match("1", "foo"); + char *result_str; + ASSERT_NOT_NULL(result); + result_str = iks_string(NULL, result); + ASSERT_STRING_EQUALS(nlsml_dtmf_instance_result, result_str); + iks_free(result_str); +} + static const char *nlsml_good_normalized = "" + " \n" + " \n" + " 01\n" + " 15\n" + " 27\n" + " 39\n" + " \n" + " \n" + "\n"; + +/** + * Test matching against adhearsion menu grammar + */ +static void test_match_adhearsion_menu_grammar(void) +{ + struct srgs_parser *parser; + struct srgs_grammar *grammar; + const char *interpretation; + + parser = srgs_parser_new("1234"); + ASSERT_NOT_NULL((grammar = srgs_parse(parser, adhearsion_menu_grammar))); + + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "0", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1", &interpretation)); + ASSERT_STRING_EQUALS("0", interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "2", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "3", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "4", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "5", &interpretation)); + ASSERT_STRING_EQUALS("1", interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "6", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "7", &interpretation)); + ASSERT_STRING_EQUALS("2", interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "8", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "9", &interpretation)); + ASSERT_STRING_EQUALS("3", interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "#", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "*", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "27", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "223", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "0123456789*#", &interpretation)); + ASSERT_NULL(interpretation); + + srgs_parser_destroy(parser); +} + +static const char *duplicate_tag_grammar = + "" + " \n" + " \n" + " 21\n" + " 25\n" + " 47\n" + " 49\n" + " \n" + " \n" + "\n"; + +/** + * Test matching with duplicate tags + */ +static void test_match_duplicate_tag_grammar(void) +{ + struct srgs_parser *parser; + struct srgs_grammar *grammar; + const char *interpretation; + + parser = srgs_parser_new("1234"); + ASSERT_NOT_NULL((grammar = srgs_parse(parser, duplicate_tag_grammar))); + + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "0", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1", &interpretation)); + ASSERT_STRING_EQUALS("2", interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "2", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "3", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "4", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "5", &interpretation)); + ASSERT_STRING_EQUALS("2", interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "6", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "7", &interpretation)); + ASSERT_STRING_EQUALS("4", interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "8", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "9", &interpretation)); + ASSERT_STRING_EQUALS("4", interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "#", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "*", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "27", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "223", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "0123456789*#", &interpretation)); + ASSERT_NULL(interpretation); + + srgs_parser_destroy(parser); +} + + static const char *adhearsion_ask_grammar = "" " \n" @@ -32,26 +153,28 @@ static void test_match_adhearsion_ask_grammar(void) { struct srgs_parser *parser; struct srgs_grammar *grammar; + const char *interpretation; parser = srgs_parser_new("1234"); ASSERT_NOT_NULL((grammar = srgs_parse(parser, adhearsion_ask_grammar))); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "0")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "2")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "3")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "4")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "5")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "6")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "7")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "8")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "9")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "#")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "*")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "27")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "223")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "0123456789*#")); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "0", &interpretation)); + ASSERT_NULL(interpretation); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "2", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "3", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "4", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "5", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "6", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "7", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "8", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "9", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "*", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "27", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "223", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "0123456789*#", &interpretation)); srgs_parser_destroy(parser); } @@ -84,26 +207,27 @@ static void test_match_multi_digit_grammar(void) { struct srgs_parser *parser; struct srgs_grammar *grammar; + const char *interpretation; parser = srgs_parser_new("1234"); ASSERT_NOT_NULL((grammar = srgs_parse(parser, multi_digit_grammar))); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "0")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "2")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "3")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "4")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "5")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "6")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "7")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "8")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "9")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "*")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "27")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "223")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "0123456789*#")); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "0", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "2", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "3", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "4", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "5", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "6", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "7", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "8", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "9", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "*", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "27", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "223", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "0123456789*#", &interpretation)); srgs_parser_destroy(parser); } @@ -137,26 +261,27 @@ static void test_match_multi_rule_grammar(void) { struct srgs_parser *parser; struct srgs_grammar *grammar; + const char *interpretation; parser = srgs_parser_new("1234"); ASSERT_NOT_NULL((grammar = srgs_parse(parser, multi_rule_grammar))); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "0")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "2")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "3")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "4")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "5")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "6")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "7")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "8")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "9")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "*")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "27")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "223")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "0123456789*#")); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "0", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "2", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "3", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "4", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "5", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "6", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "7", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "8", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "9", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "*", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "27", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "223", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "0123456789*#", &interpretation)); srgs_parser_destroy(parser); } @@ -200,28 +325,29 @@ static void test_match_rayo_example_grammar(void) { struct srgs_parser *parser; struct srgs_grammar *grammar; + const char *interpretation; parser = srgs_parser_new("1234"); ASSERT_NOT_NULL((grammar = srgs_parse(parser, rayo_example_grammar))); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "0")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "2")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "3")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "4")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "5")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "6")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "7")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "8")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "9")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "*")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "*9")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1234#")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "2321#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "27")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "223")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "0123456789*#")); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "0", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "2", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "3", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "4", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "5", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "6", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "7", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "8", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "9", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "*", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "*9", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1234#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "2321#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "27", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "223", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "0123456789*#", &interpretation)); srgs_parser_destroy(parser); } @@ -566,6 +692,7 @@ static void test_repeat_item_grammar(void) { struct srgs_parser *parser; struct srgs_grammar *grammar; + const char *interpretation; parser = srgs_parser_new("1234"); ASSERT_NULL(srgs_parse(parser, repeat_item_grammar_bad)); @@ -575,74 +702,74 @@ static void test_repeat_item_grammar(void) ASSERT_NULL(srgs_parse(parser, repeat_item_grammar_bad5)); ASSERT_NULL(srgs_parse(parser, repeat_item_grammar_bad6)); ASSERT_NOT_NULL((grammar = srgs_parse(parser, repeat_item_grammar))); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1111#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1111")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1234#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1234")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "11115#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "11115")); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1111#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1111", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1234#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1234", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "11115#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "11115", &interpretation)); ASSERT_NOT_NULL((grammar = srgs_parse(parser, repeat_item_range_grammar))); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1111#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1111")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1234#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1234")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "11115#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "11115")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "111156#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "111156")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1111567#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1111567")); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1111#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1111", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1234#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1234", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "11115#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "11115", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "111156#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "111156", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1111567#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1111567", &interpretation)); ASSERT_NOT_NULL((grammar = srgs_parse(parser, repeat_item_optional_grammar))); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1111#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1111")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1234#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1234")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "11115#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "11115")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "111156#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "111156")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1111567#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1111567")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A")); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1111#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1111", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1234#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1234", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "11115#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "11115", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "111156#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "111156", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1111567#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "1111567", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A", &interpretation)); ASSERT_NOT_NULL((grammar = srgs_parse(parser, repeat_item_plus_grammar))); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1111#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1111")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1234#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1234")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "11115#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "11115")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "111156#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "111156")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "111157#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "111157")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A")); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1111#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1111", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1234#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1234", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "11115#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "11115", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "111156#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "111156", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "111157#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "111157", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A", &interpretation)); ASSERT_NOT_NULL((grammar = srgs_parse(parser, repeat_item_star_grammar))); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1111#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1111")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1234#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1234")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "11115#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "11115")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "111156#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "111156")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "111157#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "111157")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1#")); - ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A#")); - ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A")); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1111#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1111", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1234#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1234", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "11115#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "11115", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "111156#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "111156", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "111157#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "111157", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_PARTIAL, srgs_grammar_match(grammar, "1", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A#", &interpretation)); + ASSERT_EQUALS(SMT_NO_MATCH, srgs_grammar_match(grammar, "A", &interpretation)); srgs_parser_destroy(parser); } @@ -678,12 +805,13 @@ static void test_repeat_item_range_ambiguous_grammar(void) { struct srgs_parser *parser; struct srgs_grammar *grammar; + const char *interpretation; parser = srgs_parser_new("1234"); ASSERT_NOT_NULL((grammar = srgs_parse(parser, repeat_item_range_ambiguous_grammar))); - ASSERT_EQUALS(SMT_MATCH, srgs_grammar_match(grammar, "1")); - ASSERT_EQUALS(SMT_MATCH, srgs_grammar_match(grammar, "12")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "123")); + ASSERT_EQUALS(SMT_MATCH, srgs_grammar_match(grammar, "1", &interpretation)); + ASSERT_EQUALS(SMT_MATCH, srgs_grammar_match(grammar, "12", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "123", &interpretation)); } static const char *repeat_item_range_optional_pound_grammar = @@ -722,14 +850,15 @@ static void test_repeat_item_range_optional_pound_grammar(void) { struct srgs_parser *parser; struct srgs_grammar *grammar; + const char *interpretation; parser = srgs_parser_new("1234"); ASSERT_NOT_NULL((grammar = srgs_parse(parser, repeat_item_range_optional_pound_grammar))); - ASSERT_EQUALS(SMT_MATCH, srgs_grammar_match(grammar, "1")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1#")); - ASSERT_EQUALS(SMT_MATCH, srgs_grammar_match(grammar, "12")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "12#")); - ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "123")); + ASSERT_EQUALS(SMT_MATCH, srgs_grammar_match(grammar, "1", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "1#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH, srgs_grammar_match(grammar, "12", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "12#", &interpretation)); + ASSERT_EQUALS(SMT_MATCH_END, srgs_grammar_match(grammar, "123", &interpretation)); } /* @@ -955,6 +1084,8 @@ int main(int argc, char **argv) TEST_INIT srgs_init(); TEST(test_parse_grammar); + TEST(test_match_adhearsion_menu_grammar); + TEST(test_match_duplicate_tag_grammar); TEST(test_match_adhearsion_ask_grammar); TEST(test_match_multi_digit_grammar); TEST(test_match_multi_rule_grammar); diff --git a/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c b/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c index 90724d42d6..d992dfd103 100644 --- a/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c +++ b/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c @@ -481,7 +481,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_xml_cdr_load) /* parse the config */ if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); - return SWITCH_STATUS_TERM; + return SWITCH_STATUS_FALSE; } if ((settings = switch_xml_child(cfg, "settings"))) { diff --git a/src/switch_caller.c b/src/switch_caller.c index d0c4ec87d3..02de5575aa 100644 --- a/src/switch_caller.c +++ b/src/switch_caller.c @@ -141,6 +141,8 @@ SWITCH_DECLARE(switch_caller_profile_t *) switch_caller_profile_dup(switch_memor if (tocopy->times) { profile->old_times = (switch_channel_timetable_t *) switch_core_alloc(profile->pool, sizeof(switch_channel_timetable_t)); *profile->old_times = *tocopy->times; + } else { + tocopy->times = (switch_channel_timetable_t *) switch_core_alloc(tocopy->pool, sizeof(*tocopy->times)); } if (tocopy->soft) { diff --git a/src/switch_core.c b/src/switch_core.c index 6529166686..7782265dc3 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1963,9 +1963,18 @@ static void switch_load_core_config(const char *file) switch_core_min_idle_cpu(atof(val)); } else if (!strcasecmp(var, "tipping-point") && !zstr(val)) { runtime.tipping_point = atoi(val); + } else if (!strcasecmp(var, "events-use-dispatch") && !zstr(val)) { + runtime.events_use_dispatch = 1; } else if (!strcasecmp(var, "initial-event-threads") && !zstr(val)) { - int tmp = atoi(val); + int tmp; + if (!runtime.events_use_dispatch) { + runtime.events_use_dispatch = 1; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Implicitly setting events-use-dispatch based on usage of this initial-event-threads parameter.\n"); + } + + tmp = atoi(val); if (tmp > runtime.cpu_count / 2) { tmp = runtime.cpu_count / 2; diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 5f8386505e..2b3c3b6d66 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -79,6 +79,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core } } + if (status == SWITCH_STATUS_INUSE) { + *frame = &runtime.dummy_cng_frame; + switch_yield(20000); + return SWITCH_STATUS_SUCCESS; + } + if (status != SWITCH_STATUS_SUCCESS) { goto done; } @@ -229,6 +235,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi } } + if (status == SWITCH_STATUS_INUSE) { + *frame = &runtime.dummy_cng_frame; + switch_yield(20000); + return SWITCH_STATUS_SUCCESS; + } + if (!SWITCH_READ_ACCEPTABLE(status) || !session->read_codec || !switch_core_codec_ready(session->read_codec)) { *frame = NULL; return SWITCH_STATUS_FALSE; diff --git a/src/switch_core_media.c b/src/switch_core_media.c index b18ec859e8..eccb0774ff 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -1231,14 +1231,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session if (switch_mutex_trylock(engine->read_mutex) != SWITCH_STATUS_SUCCESS) { /* return CNG, another thread is already reading */ - *frame = &engine->read_frame; - switch_set_flag((*frame), SFF_CNG); - (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet; - memset((*frame)->data, 0, (*frame)->datalen); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being read for %s\n", switch_channel_get_name(session->channel), type2str(type)); - switch_yield(10000); - return SWITCH_STATUS_SUCCESS; + return SWITCH_STATUS_INUSE; } @@ -3890,7 +3885,8 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi mh->up = 1; switch_mutex_lock(mh->cond_mutex); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread started\n", switch_channel_get_name(session->channel)); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread started. Echo is %s\n", + switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off"); switch_core_session_refresh_video(session); while (switch_channel_up_nosig(channel)) { diff --git a/src/switch_core_session.c b/src/switch_core_session.c index a67359d677..07b0391bf4 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1586,9 +1586,9 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread_pool_worker(switch_th switch_mutex_lock(session_manager.mutex); session_manager.running++; switch_mutex_unlock(session_manager.mutex); - +#ifdef DEBUG_THREAD_POOL switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Worker Thread %ld Started\n", (long) thread); - +#endif while(session_manager.ready) { switch_status_t check_status; @@ -1616,18 +1616,22 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread_pool_worker(switch_th switch_mutex_lock(session_manager.mutex); session_manager.busy++; switch_mutex_unlock(session_manager.mutex); - +#ifdef DEBUG_THREAD_POOL switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Worker Thread %ld Processing\n", (long) thread); - +#endif td->func(thread, td->obj); - if (td->alloc) { + if (td->pool) { + switch_memory_pool_t *pool = td->pool; + td = NULL; + switch_core_destroy_memory_pool(&pool); + } else if (td->alloc) { free(td); } - +#ifdef DEBUG_THREAD_POOL switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Worker Thread %ld Done Processing\n", (long) thread); - +#endif switch_mutex_lock(session_manager.mutex); session_manager.busy--; switch_mutex_unlock(session_manager.mutex); @@ -1639,9 +1643,9 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread_pool_worker(switch_th check++; } } - +#ifdef DEBUG_THREAD_POOL switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Worker Thread %ld Ended\n", (long) thread); - +#endif switch_mutex_lock(session_manager.mutex); session_manager.running--; switch_mutex_unlock(session_manager.mutex); @@ -1725,9 +1729,10 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread_pool_manager(switch_t if (++x == 300) { if (session_manager.popping) { +#ifdef DEBUG_THREAD_POOL switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Thread pool: running:%d busy:%d popping:%d\n", session_manager.running, session_manager.busy, session_manager.popping); - +#endif switch_queue_interrupt_all(session_manager.thread_queue); x--; @@ -2523,11 +2528,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_async(sw SWITCH_DECLARE(void) switch_core_session_video_reset(switch_core_session_t *session) { - if (switch_channel_test_flag(session->channel, CF_VIDEO)) { - switch_channel_set_flag(session->channel, CF_VIDEO_ECHO); - switch_channel_clear_flag(session->channel, CF_VIDEO_PASSIVE); - switch_core_session_refresh_video(session); - } + switch_channel_set_flag(session->channel, CF_VIDEO_ECHO); + switch_channel_clear_flag(session->channel, CF_VIDEO_PASSIVE); + switch_core_session_refresh_video(session); } SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flags(switch_core_session_t *session, const char *app, diff --git a/src/switch_event.c b/src/switch_event.c index b3ef5f0cc2..b87d1d4d4b 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -36,6 +36,7 @@ #include #include #include "tpl.h" +#include "private/switch_core_pvt.h" //#define SWITCH_EVENT_RECYCLE #define DISPATCH_QUEUE_LEN 10000 @@ -154,8 +155,6 @@ static char *EVENT_NAMES[] = { "MESSAGE", "PRESENCE_IN", "NOTIFY_IN", - "PHONE_FEATURE", - "PHONE_FEATURE_SUBSCRIBE", "PRESENCE_OUT", "PRESENCE_PROBE", "MESSAGE_WAITING", @@ -174,6 +173,8 @@ static char *EVENT_NAMES[] = { "RE_SCHEDULE", "RELOADXML", "NOTIFY", + "PHONE_FEATURE", + "PHONE_FEATURE_SUBSCRIBE", "SEND_MESSAGE", "RECV_MESSAGE", "REQUEST_PARAMS", @@ -244,6 +245,34 @@ static int switch_events_match(switch_event_t *event, switch_event_node_t *node) return match; } + +static void *SWITCH_THREAD_FUNC switch_event_deliver_thread(switch_thread_t *thread, void *obj) +{ + switch_event_t *event = (switch_event_t *) obj; + + switch_event_deliver(&event); + + return NULL; +} + +static void switch_event_deliver_thread_pool(switch_event_t **event) +{ + switch_thread_data_t *td; + + td = malloc(sizeof(*td)); + switch_assert(td); + + td->alloc = 1; + td->func = switch_event_deliver_thread; + td->obj = *event; + td->pool = NULL; + + *event = NULL; + + switch_thread_pool_launch_thread(&td); + +} + static void *SWITCH_THREAD_FUNC switch_event_dispatch_thread(switch_thread_t *thread, void *obj) { switch_queue_t *queue = (switch_queue_t *) obj; @@ -489,19 +518,22 @@ SWITCH_DECLARE(switch_status_t) switch_event_shutdown(void) SYSTEM_RUNNING = 0; switch_mutex_unlock(EVENT_QUEUE_MUTEX); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping dispatch queues\n"); + if (runtime.events_use_dispatch) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping dispatch queues\n"); - for(x = 0; x < (uint32_t)DISPATCH_THREAD_COUNT; x++) { - switch_queue_trypush(EVENT_DISPATCH_QUEUE, NULL); - } + for(x = 0; x < (uint32_t)DISPATCH_THREAD_COUNT; x++) { + switch_queue_trypush(EVENT_DISPATCH_QUEUE, NULL); + } + - switch_queue_interrupt_all(EVENT_DISPATCH_QUEUE); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping dispatch threads\n"); - - for(x = 0; x < (uint32_t)DISPATCH_THREAD_COUNT; x++) { - switch_status_t st; - switch_thread_join(&st, EVENT_DISPATCH_QUEUE_THREADS[x]); + switch_queue_interrupt_all(EVENT_DISPATCH_QUEUE); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping dispatch threads\n"); + + for(x = 0; x < (uint32_t)DISPATCH_THREAD_COUNT; x++) { + switch_status_t st; + switch_thread_join(&st, EVENT_DISPATCH_QUEUE_THREADS[x]); + } } x = 0; @@ -513,7 +545,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_shutdown(void) last = THREAD_COUNT; } - { + if (runtime.events_use_dispatch) { void *pop = NULL; switch_event_t *event = NULL; @@ -622,19 +654,21 @@ SWITCH_DECLARE(switch_status_t) switch_event_init(switch_memory_pool_t *pool) //switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - - switch_queue_create(&EVENT_DISPATCH_QUEUE, DISPATCH_QUEUE_LEN * MAX_DISPATCH, pool); - switch_event_launch_dispatch_threads(1); + if (runtime.events_use_dispatch) { + switch_queue_create(&EVENT_DISPATCH_QUEUE, DISPATCH_QUEUE_LEN * MAX_DISPATCH, pool); + switch_event_launch_dispatch_threads(1); + } //switch_thread_create(&EVENT_QUEUE_THREADS[0], thd_attr, switch_event_thread, EVENT_QUEUE[0], RUNTIME_POOL); //switch_thread_create(&EVENT_QUEUE_THREADS[1], thd_attr, switch_event_thread, EVENT_QUEUE[1], RUNTIME_POOL); //switch_thread_create(&EVENT_QUEUE_THREADS[2], thd_attr, switch_event_thread, EVENT_QUEUE[2], RUNTIME_POOL); - while (!THREAD_COUNT) { - switch_cond_next(); + if (runtime.events_use_dispatch) { + while (!THREAD_COUNT) { + switch_cond_next(); + } } - switch_mutex_lock(EVENT_QUEUE_MUTEX); SYSTEM_RUNNING = 1; switch_mutex_unlock(EVENT_QUEUE_MUTEX); @@ -1884,9 +1918,15 @@ SWITCH_DECLARE(switch_status_t) switch_event_fire_detailed(const char *file, con (*event)->event_user_data = user_data; } - if (switch_event_queue_dispatch_event(event) != SWITCH_STATUS_SUCCESS) { - switch_event_destroy(event); - return SWITCH_STATUS_FALSE; + + + if (runtime.events_use_dispatch) { + if (switch_event_queue_dispatch_event(event) != SWITCH_STATUS_SUCCESS) { + switch_event_destroy(event); + return SWITCH_STATUS_FALSE; + } + } else { + switch_event_deliver_thread_pool(event); } return SWITCH_STATUS_SUCCESS; diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 9f4ea8cf5b..f5d84fbb76 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -1711,9 +1711,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session name = cp->caller_id_name; num = cp->caller_id_number; } - - my_cp->callee_id_name = switch_core_strdup(my_cp->pool, name); - my_cp->callee_id_number = switch_core_strdup(my_cp->pool, num); } sanity = 300; diff --git a/src/switch_rtp.c b/src/switch_rtp.c index b75835a270..ddebe10168 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -5920,6 +5920,7 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra } send_msg->header.ssrc = htonl(rtp_session->ssrc); + send_msg->header.seq = htons(++rtp_session->seq); } if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, frame->packet, &bytes) != SWITCH_STATUS_SUCCESS) { diff --git a/src/switch_xml.c b/src/switch_xml.c index d82435dd3f..de171a933e 100644 --- a/src/switch_xml.c +++ b/src/switch_xml.c @@ -2244,6 +2244,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_set_open_root_function(switch_xml_ope SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **err) { switch_xml_t root = NULL; + switch_event_t *event; switch_mutex_lock(XML_LOCK); @@ -2252,6 +2253,15 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **e } switch_mutex_unlock(XML_LOCK); + + if (root) { + if (switch_event_create(&event, SWITCH_EVENT_RELOADXML) == SWITCH_STATUS_SUCCESS) { + if (switch_event_fire(&event) != SWITCH_STATUS_SUCCESS) { + switch_event_destroy(&event); + } + } + } + return root; } @@ -2288,12 +2298,6 @@ SWITCH_DECLARE_NONSTD(switch_xml_t) __switch_xml_open_root(uint8_t reload, const } if (errcnt == 0) { - switch_event_t *event; - if (switch_event_create(&event, SWITCH_EVENT_RELOADXML) == SWITCH_STATUS_SUCCESS) { - if (switch_event_fire(&event) != SWITCH_STATUS_SUCCESS) { - switch_event_destroy(&event); - } - } r = switch_xml_root(); }