From 43e6b6fa23ac87fc720b12011bf4f3926c572513 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 19 May 2007 04:07:48 +0000 Subject: [PATCH] add dtmf generation and pause to let mike have a turn git-svn-id: http://svn.openzap.org/svn/openzap/trunk@36 a93c3328-9c30-0410-af19-c9cd2b2d52af --- libs/freetdm/src/include/openzap.h | 177 +++------------------- libs/freetdm/src/include/zap_types.h | 196 +++++++++++++++++++++++++ libs/freetdm/src/openzap.c | 211 +++++++++++++++++++++++---- libs/freetdm/src/zap_wanpipe.c | 14 -- 4 files changed, 398 insertions(+), 200 deletions(-) create mode 100644 libs/freetdm/src/include/zap_types.h diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h index 67db68761a..c6e4e79343 100644 --- a/libs/freetdm/src/include/openzap.h +++ b/libs/freetdm/src/include/openzap.h @@ -78,10 +78,12 @@ #include #endif #include +#include "zap_types.h" #include "hashtable.h" #include "zap_config.h" #include "g711.h" #include "libteletone.h" +#include "zap_buffer.h" #ifdef NDEBUG #undef assert @@ -91,17 +93,7 @@ #define ZAP_MAX_CHANNELS_SPAN 513 #define ZAP_MAX_SPANS_INTERFACE 33 -#ifdef WIN32 -#include -typedef HANDLE zap_socket_t; -#else -typedef int zap_socket_t; -#endif -typedef size_t zap_size_t; -struct zap_software_interface; - -#define ZAP_COMMAND_OBJ_INT *((int *)obj) #define zap_true(expr)\ (expr && ( !strcasecmp(expr, "yes") ||\ @@ -156,136 +148,6 @@ struct zap_software_interface; #define zap_socket_close(it) if (it > -1) { close(it); it = -1;} -typedef enum { - ZAP_TOP_DOWN, - ZAP_BOTTOM_UP -} zap_direction_t; - -typedef enum { - ZAP_SUCCESS, - ZAP_FAIL, - ZAP_MEMERR, - ZAP_TIMEOUT -} zap_status_t; - -typedef enum { - ZAP_NO_FLAGS = 0, - ZAP_READ = (1 << 0), - ZAP_WRITE = (1 << 1), - ZAP_ERROR = (1 << 2) -} zap_wait_flag_t; - -typedef enum { - ZAP_CODEC_ULAW = 0, - ZAP_CODEC_ALAW = 8, - ZAP_CODEC_SLIN = 10, - ZAP_CODEC_NONE = (1 << 31) -} zap_codec_t; - -typedef enum { - ZAP_TONE_DTMF = (1 << 0) -} zap_tone_type_t; - -typedef enum { - ZAP_COMMAND_NOOP, - ZAP_COMMAND_SET_INTERVAL, - ZAP_COMMAND_GET_INTERVAL, - ZAP_COMMAND_SET_CODEC, - ZAP_COMMAND_GET_CODEC, - ZAP_COMMAND_ENABLE_TONE_DETECT, - ZAP_COMMAND_DISABLE_TONE_DETECT -} zap_command_t; - -typedef enum { - ZAP_SPAN_CONFIGURED = (1 << 0), - ZAP_SPAN_READY = (1 << 1) -} zap_span_flag_t; - -typedef enum { - ZAP_CHAN_TYPE_B, - ZAP_CHAN_TYPE_DQ921, - ZAP_CHAN_TYPE_DQ931, - ZAP_CHAN_TYPE_FXS, - ZAP_CHAN_TYPE_FXO -} zap_chan_type_t; - -typedef enum { - ZAP_CHANNEL_FEATURE_DTMF_DETECT = (1 << 0) -} zap_channel_feature_t; - -typedef enum { - ZAP_CHANNEL_CONFIGURED = (1 << 0), - ZAP_CHANNEL_READY = (1 << 1), - ZAP_CHANNEL_OPEN = (1 << 2), - ZAP_CHANNEL_DTMF_DETECT = (1 << 3), - ZAP_CHANNEL_SUPRESS_DTMF = (1 << 4) -} zap_channel_flag_t; - -typedef struct zap_channel zap_channel_t; -typedef struct zap_event zap_event_t; - -#define ZINT_EVENT_CB_ARGS (zap_channel_t *zchan, zap_event_t *event) -#define ZINT_CODEC_ARGS (void *data, zap_size_t max, zap_size_t *datalen) -#define ZINT_CONFIGURE_ARGS (struct zap_software_interface *zint) -#define ZINT_OPEN_ARGS (zap_channel_t *zchan) -#define ZINT_CLOSE_ARGS (zap_channel_t *zchan) -#define ZINT_COMMAND_ARGS (zap_channel_t *zchan, zap_command_t command, void *obj) -#define ZINT_WAIT_ARGS (zap_channel_t *zchan, zap_wait_flag_t *flags, unsigned to) -#define ZINT_READ_ARGS (zap_channel_t *zchan, void *data, zap_size_t *datalen) -#define ZINT_WRITE_ARGS (zap_channel_t *zchan, void *data, zap_size_t *datalen) - -typedef zap_status_t (*zint_event_cb_t) ZINT_EVENT_CB_ARGS ; -typedef zap_status_t (*zint_codec_t) ZINT_CODEC_ARGS ; -typedef zap_status_t (*zint_configure_t) ZINT_CONFIGURE_ARGS ; -typedef zap_status_t (*zint_open_t) ZINT_OPEN_ARGS ; -typedef zap_status_t (*zint_close_t) ZINT_CLOSE_ARGS ; -typedef zap_status_t (*zint_command_t) ZINT_COMMAND_ARGS ; -typedef zap_status_t (*zint_wait_t) ZINT_WAIT_ARGS ; -typedef zap_status_t (*zint_read_t) ZINT_READ_ARGS ; -typedef zap_status_t (*zint_write_t) ZINT_WRITE_ARGS ; - -#define ZINT_EVENT_CB_FUNCTION(name) zap_status_t name ZINT_EVENT_CB_ARGS -#define ZINT_CODEC_FUNCTION(name) zap_status_t name ZINT_CODEC_ARGS -#define ZINT_CONFIGURE_FUNCTION(name) zap_status_t name ZINT_CONFIGURE_ARGS -#define ZINT_OPEN_FUNCTION(name) zap_status_t name ZINT_OPEN_ARGS -#define ZINT_CLOSE_FUNCTION(name) zap_status_t name ZINT_CLOSE_ARGS -#define ZINT_COMMAND_FUNCTION(name) zap_status_t name ZINT_COMMAND_ARGS -#define ZINT_WAIT_FUNCTION(name) zap_status_t name ZINT_WAIT_ARGS -#define ZINT_READ_FUNCTION(name) zap_status_t name ZINT_READ_ARGS -#define ZINT_WRITE_FUNCTION(name) zap_status_t name ZINT_WRITE_ARGS - -#define ZINT_CONFIGURE_MUZZLE assert(zint != NULL) -#define ZINT_OPEN_MUZZLE assert(zchan != NULL) -#define ZINT_CLOSE_MUZZLE assert(zchan != NULL) -#define ZINT_COMMAND_MUZZLE assert(zchan != NULL); assert(command != 0); assert(obj != NULL) -#define ZINT_WAIT_MUZZLE assert(zchan != NULL); assert(flags != 0); assert(to != 0) -#define ZINT_READ_MUZZLE assert(zchan != NULL); assert(data != NULL); assert(datalen != NULL) -#define ZINT_WRITE_MUZZLE assert(zchan != NULL); assert(data != NULL); assert(datalen != NULL) - -#define ZAP_PRE __FILE__, __FUNCTION__, __LINE__ - -#define ZAP_LOG_LEVEL_DEBUG 7 -#define ZAP_LOG_LEVEL_INFO 6 -#define ZAP_LOG_LEVEL_NOTICE 5 -#define ZAP_LOG_LEVEL_WARNING 4 -#define ZAP_LOG_LEVEL_ERROR 3 -#define ZAP_LOG_LEVEL_CRIT 2 -#define ZAP_LOG_LEVEL_ALERT 1 -#define ZAP_LOG_LEVEL_EMERG 0 - -#define ZAP_LOG_DEBUG ZAP_PRE, ZAP_LOG_LEVEL_DEBUG -#define ZAP_LOG_INFO ZAP_PRE, ZAP_LOG_LEVEL_INFO -#define ZAP_LOG_NOTICE ZAP_PRE, ZAP_LOG_LEVEL_NOTICE -#define ZAP_LOG_WARNING ZAP_PRE, ZAP_LOG_LEVEL_WARNING -#define ZAP_LOG_ERROR ZAP_PRE, ZAP_LOG_LEVEL_ERROR -#define ZAP_LOG_CRIT ZAP_PRE, ZAP_LOG_LEVEL_CRIT -#define ZAP_LOG_ALERT ZAP_PRE, ZAP_LOG_LEVEL_ALERT -#define ZAP_LOG_EMERG ZAP_PRE, ZAP_LOG_LEVEL_EMERG - -typedef enum { - ZAP_EVENT_NONE, - ZAP_EVENT_DTMF -} zap_event_type_t; struct zap_event { zap_event_type_t e_type; @@ -293,8 +155,8 @@ struct zap_event { }; struct zap_channel { - unsigned span_id; - unsigned chan_id; + uint32_t span_id; + uint32_t chan_id; zap_chan_type_t type; zap_socket_t sockfd; zap_channel_flag_t flags; @@ -306,24 +168,26 @@ struct zap_channel { char last_error[256]; zint_event_cb_t event_callback; void *mod_data; - unsigned skip_read_frames; + uint32_t skip_read_frames; + zap_buffer_t *dtmf_buffer; + uint32_t dtmf_on; + uint32_t dtmf_off; + teletone_generation_session_t tone_session; struct zap_span *span; struct zap_software_interface *zint; }; struct zap_span { - unsigned span_id; - unsigned chan_count; + uint32_t span_id; + uint32_t chan_count; zap_span_flag_t flags; struct zap_software_interface *zint; zint_event_cb_t event_callback; zap_channel_t channels[ZAP_MAX_CHANNELS_SPAN]; }; -typedef struct zap_span zap_span_t; -typedef void (*zap_logger_t)(char *file, const char *func, int line, int level, char *fmt, ...); extern zap_logger_t zap_log; struct zap_software_interface { @@ -335,31 +199,26 @@ struct zap_software_interface { zint_wait_t wait; zint_read_t read; zint_write_t write; - unsigned span_index; + uint32_t span_index; struct zap_span spans[ZAP_MAX_SPANS_INTERFACE]; }; -typedef struct zap_software_interface zap_software_interface_t; - -zap_status_t zap_span_find(const char *name, unsigned id, zap_span_t **span); +zap_status_t zap_span_find(const char *name, uint32_t id, zap_span_t **span); zap_status_t zap_span_create(zap_software_interface_t *zint, zap_span_t **span); zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_chan_type_t type, zap_channel_t **chan); zap_status_t zap_span_set_event_callback(zap_span_t *span, zint_event_cb_t event_callback); zap_status_t zap_channel_set_event_callback(zap_channel_t *zchan, zint_event_cb_t event_callback); -zap_status_t zap_channel_open(const char *name, unsigned span_id, unsigned chan_id, zap_channel_t **zchan); -zap_status_t zap_channel_open_any(const char *name, unsigned span_id, zap_direction_t direction, zap_channel_t **zchan); +zap_status_t zap_channel_open(const char *name, uint32_t span_id, uint32_t chan_id, zap_channel_t **zchan); +zap_status_t zap_channel_open_any(const char *name, uint32_t span_id, zap_direction_t direction, zap_channel_t **zchan); zap_status_t zap_channel_close(zap_channel_t **zchan); zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, void *obj); -zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t *flags, unsigned to); +zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t *flags, uint32_t to); zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *datalen); zap_status_t zap_channel_write(zap_channel_t *zchan, void *data, zap_size_t *datalen); zap_status_t zap_global_init(void); zap_status_t zap_global_destroy(void); void zap_global_set_logger(zap_logger_t logger); void zap_global_set_default_logger(int level); -unsigned zap_separate_string(char *buf, char delim, char **array, int arraylen); -typedef struct hashtable zap_hash_t; -typedef struct hashtable_itr zap_hash_itr_t; -typedef struct key zap_hash_key_t; -typedef struct value zap_hash_val_t; +uint32_t zap_separate_string(char *buf, char delim, char **array, int arraylen); + #endif diff --git a/libs/freetdm/src/include/zap_types.h b/libs/freetdm/src/include/zap_types.h new file mode 100644 index 0000000000..b8613e613b --- /dev/null +++ b/libs/freetdm/src/include/zap_types.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2007, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ZAP_TYPES_H +#define ZAP_TYPES_H + +#ifdef WIN32 +#include +typedef HANDLE zap_socket_t; +#else +#include +typedef int zap_socket_t; +#endif + +typedef size_t zap_size_t; +struct zap_software_interface; + +#define ZAP_COMMAND_OBJ_INT *((int *)obj) +#define ZAP_COMMAND_OBJ_CHAR_P (char *)obj + +typedef enum { + ZAP_TOP_DOWN, + ZAP_BOTTOM_UP +} zap_direction_t; + +typedef enum { + ZAP_SUCCESS, + ZAP_FAIL, + ZAP_MEMERR, + ZAP_TIMEOUT +} zap_status_t; + +typedef enum { + ZAP_NO_FLAGS = 0, + ZAP_READ = (1 << 0), + ZAP_WRITE = (1 << 1), + ZAP_ERROR = (1 << 2) +} zap_wait_flag_t; + +typedef enum { + ZAP_CODEC_ULAW = 0, + ZAP_CODEC_ALAW = 8, + ZAP_CODEC_SLIN = 10, + ZAP_CODEC_NONE = (1 << 31) +} zap_codec_t; + +typedef enum { + ZAP_TONE_DTMF = (1 << 0) +} zap_tone_type_t; + +typedef enum { + ZAP_COMMAND_NOOP, + ZAP_COMMAND_SET_INTERVAL, + ZAP_COMMAND_GET_INTERVAL, + ZAP_COMMAND_SET_CODEC, + ZAP_COMMAND_GET_CODEC, + ZAP_COMMAND_ENABLE_TONE_DETECT, + ZAP_COMMAND_DISABLE_TONE_DETECT, + ZAP_COMMAND_SEND_DTMF, + ZAP_COMMAND_SET_DTMF_ON_PERIOD, + ZAP_COMMAND_GET_DTMF_ON_PERIOD, + ZAP_COMMAND_SET_DTMF_OFF_PERIOD, + ZAP_COMMAND_GET_DTMF_OFF_PERIOD +} zap_command_t; + +typedef enum { + ZAP_SPAN_CONFIGURED = (1 << 0), + ZAP_SPAN_READY = (1 << 1) +} zap_span_flag_t; + +typedef enum { + ZAP_CHAN_TYPE_B, + ZAP_CHAN_TYPE_DQ921, + ZAP_CHAN_TYPE_DQ931, + ZAP_CHAN_TYPE_FXS, + ZAP_CHAN_TYPE_FXO +} zap_chan_type_t; + +typedef enum { + ZAP_CHANNEL_FEATURE_DTMF = (1 << 0), + ZAP_CHANNEL_FEATURE_CODECS = (1 << 1) +} zap_channel_feature_t; + +typedef enum { + ZAP_CHANNEL_CONFIGURED = (1 << 0), + ZAP_CHANNEL_READY = (1 << 1), + ZAP_CHANNEL_OPEN = (1 << 2), + ZAP_CHANNEL_DTMF_DETECT = (1 << 3), + ZAP_CHANNEL_SUPRESS_DTMF = (1 << 4), + ZAP_CHANNEL_TRANSCODE = (1 << 5) +} zap_channel_flag_t; + +typedef struct zap_channel zap_channel_t; +typedef struct zap_event zap_event_t; + +#define ZINT_EVENT_CB_ARGS (zap_channel_t *zchan, zap_event_t *event) +#define ZINT_CODEC_ARGS (void *data, zap_size_t max, zap_size_t *datalen) +#define ZINT_CONFIGURE_ARGS (struct zap_software_interface *zint) +#define ZINT_OPEN_ARGS (zap_channel_t *zchan) +#define ZINT_CLOSE_ARGS (zap_channel_t *zchan) +#define ZINT_COMMAND_ARGS (zap_channel_t *zchan, zap_command_t command, void *obj) +#define ZINT_WAIT_ARGS (zap_channel_t *zchan, zap_wait_flag_t *flags, uint32_t to) +#define ZINT_READ_ARGS (zap_channel_t *zchan, void *data, zap_size_t *datalen) +#define ZINT_WRITE_ARGS (zap_channel_t *zchan, void *data, zap_size_t *datalen) + +typedef zap_status_t (*zint_event_cb_t) ZINT_EVENT_CB_ARGS ; +typedef zap_status_t (*zint_codec_t) ZINT_CODEC_ARGS ; +typedef zap_status_t (*zint_configure_t) ZINT_CONFIGURE_ARGS ; +typedef zap_status_t (*zint_open_t) ZINT_OPEN_ARGS ; +typedef zap_status_t (*zint_close_t) ZINT_CLOSE_ARGS ; +typedef zap_status_t (*zint_command_t) ZINT_COMMAND_ARGS ; +typedef zap_status_t (*zint_wait_t) ZINT_WAIT_ARGS ; +typedef zap_status_t (*zint_read_t) ZINT_READ_ARGS ; +typedef zap_status_t (*zint_write_t) ZINT_WRITE_ARGS ; + +#define ZINT_EVENT_CB_FUNCTION(name) zap_status_t name ZINT_EVENT_CB_ARGS +#define ZINT_CODEC_FUNCTION(name) zap_status_t name ZINT_CODEC_ARGS +#define ZINT_CONFIGURE_FUNCTION(name) zap_status_t name ZINT_CONFIGURE_ARGS +#define ZINT_OPEN_FUNCTION(name) zap_status_t name ZINT_OPEN_ARGS +#define ZINT_CLOSE_FUNCTION(name) zap_status_t name ZINT_CLOSE_ARGS +#define ZINT_COMMAND_FUNCTION(name) zap_status_t name ZINT_COMMAND_ARGS +#define ZINT_WAIT_FUNCTION(name) zap_status_t name ZINT_WAIT_ARGS +#define ZINT_READ_FUNCTION(name) zap_status_t name ZINT_READ_ARGS +#define ZINT_WRITE_FUNCTION(name) zap_status_t name ZINT_WRITE_ARGS + +#define ZINT_CONFIGURE_MUZZLE assert(zint != NULL) +#define ZINT_OPEN_MUZZLE assert(zchan != NULL) +#define ZINT_CLOSE_MUZZLE assert(zchan != NULL) +#define ZINT_COMMAND_MUZZLE assert(zchan != NULL); assert(command != 0); assert(obj != NULL) +#define ZINT_WAIT_MUZZLE assert(zchan != NULL); assert(flags != 0); assert(to != 0) +#define ZINT_READ_MUZZLE assert(zchan != NULL); assert(data != NULL); assert(datalen != NULL) +#define ZINT_WRITE_MUZZLE assert(zchan != NULL); assert(data != NULL); assert(datalen != NULL) + +#define ZAP_PRE __FILE__, __FUNCTION__, __LINE__ + +#define ZAP_LOG_LEVEL_DEBUG 7 +#define ZAP_LOG_LEVEL_INFO 6 +#define ZAP_LOG_LEVEL_NOTICE 5 +#define ZAP_LOG_LEVEL_WARNING 4 +#define ZAP_LOG_LEVEL_ERROR 3 +#define ZAP_LOG_LEVEL_CRIT 2 +#define ZAP_LOG_LEVEL_ALERT 1 +#define ZAP_LOG_LEVEL_EMERG 0 + +#define ZAP_LOG_DEBUG ZAP_PRE, ZAP_LOG_LEVEL_DEBUG +#define ZAP_LOG_INFO ZAP_PRE, ZAP_LOG_LEVEL_INFO +#define ZAP_LOG_NOTICE ZAP_PRE, ZAP_LOG_LEVEL_NOTICE +#define ZAP_LOG_WARNING ZAP_PRE, ZAP_LOG_LEVEL_WARNING +#define ZAP_LOG_ERROR ZAP_PRE, ZAP_LOG_LEVEL_ERROR +#define ZAP_LOG_CRIT ZAP_PRE, ZAP_LOG_LEVEL_CRIT +#define ZAP_LOG_ALERT ZAP_PRE, ZAP_LOG_LEVEL_ALERT +#define ZAP_LOG_EMERG ZAP_PRE, ZAP_LOG_LEVEL_EMERG + +typedef enum { + ZAP_EVENT_NONE, + ZAP_EVENT_DTMF +} zap_event_type_t; + +typedef struct zap_span zap_span_t; +typedef void (*zap_logger_t)(char *file, const char *func, int line, int level, char *fmt, ...); +typedef struct zap_software_interface zap_software_interface_t; +typedef struct hashtable zap_hash_t; +typedef struct hashtable_itr zap_hash_itr_t; +typedef struct key zap_hash_key_t; +typedef struct value zap_hash_val_t; +#endif diff --git a/libs/freetdm/src/openzap.c b/libs/freetdm/src/openzap.c index 1e215cf785..37a39c71cf 100644 --- a/libs/freetdm/src/openzap.c +++ b/libs/freetdm/src/openzap.c @@ -31,7 +31,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - #include "openzap.h" #include #ifdef ZAP_WANPIPE_SUPPORT @@ -108,7 +107,6 @@ static void default_logger(char *file, const char *func, int line, int level, ch } - zap_logger_t zap_log = null_logger; void zap_global_set_logger(zap_logger_t logger) @@ -135,10 +133,10 @@ static int equalkeys(void *k1, void *k2) return strcmp((char *) k1, (char *) k2) ? 0 : 1; } -static unsigned hashfromstring(void *ky) +static uint32_t hashfromstring(void *ky) { unsigned char *str = (unsigned char *) ky; - unsigned hash = 0; + uint32_t hash = 0; int c; while ((c = *str++)) { @@ -186,7 +184,7 @@ zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_cha return ZAP_FAIL; } -zap_status_t zap_span_find(const char *name, unsigned id, zap_span_t **span) +zap_status_t zap_span_find(const char *name, uint32_t id, zap_span_t **span) { zap_software_interface_t *zint = (zap_software_interface_t *) hashtable_search(globals.interface_hash, (char *)name); zap_span_t *fspan; @@ -223,14 +221,14 @@ zap_status_t zap_channel_set_event_callback(zap_channel_t *zchan, zint_event_cb_ return ZAP_SUCCESS; } -zap_status_t zap_channel_open_any(const char *name, unsigned span_id, zap_direction_t direction, zap_channel_t **zchan) +zap_status_t zap_channel_open_any(const char *name, uint32_t span_id, zap_direction_t direction, zap_channel_t **zchan) { zap_software_interface_t *zint = (zap_software_interface_t *) hashtable_search(globals.interface_hash, (char *)name); zap_status_t status = ZAP_FAIL; zap_channel_t *check; - unsigned i,j; + uint32_t i,j; zap_span_t *span; - unsigned span_max; + uint32_t span_max; if (!zint) { zap_log(ZAP_LOG_ERROR, "Invalid interface name!\n"); @@ -319,7 +317,7 @@ zap_status_t zap_channel_open_any(const char *name, unsigned span_id, zap_direct return status; } -zap_status_t zap_channel_open(const char *name, unsigned span_id, unsigned chan_id, zap_channel_t **zchan) +zap_status_t zap_channel_open(const char *name, uint32_t span_id, uint32_t chan_id, zap_channel_t **zchan) { zap_software_interface_t *zint = (zap_software_interface_t *) hashtable_search(globals.interface_hash, (char *)name); zap_status_t status = ZAP_FAIL; @@ -357,6 +355,14 @@ zap_status_t zap_channel_close(zap_channel_t **zchan) check->event_callback = NULL; zap_clear_flag(check, ZAP_CHANNEL_DTMF_DETECT); zap_clear_flag(check, ZAP_CHANNEL_SUPRESS_DTMF); + if (check->tone_session.buffer) { + teletone_destroy_session(&check->tone_session); + memset(&check->tone_session, 0, sizeof(check->tone_session)); + } + if (check->dtmf_buffer) { + zap_buffer_destroy(&check->dtmf_buffer); + } + check->dtmf_on = check->dtmf_off = 0; *zchan = NULL; } } @@ -365,6 +371,38 @@ zap_status_t zap_channel_close(zap_channel_t **zchan) } +static zap_status_t zchan_activate_dtmf_buffer(zap_channel_t *zchan) +{ + + if (zchan->dtmf_buffer) { + return ZAP_SUCCESS; + } + + if (zap_buffer_create(&zchan->dtmf_buffer, 1024, 3192, 0) != ZAP_SUCCESS) { + zap_log(ZAP_LOG_ERROR, "Failed to allocate DTMF Buffer!\n"); + snprintf(zchan->last_error, sizeof(zchan->last_error), "buffer error"); + return ZAP_FAIL; + } else { + zap_log(ZAP_LOG_DEBUG, "Created DTMF Buffer!\n"); + } + + if (!zchan->dtmf_on) { + zchan->dtmf_on = 150; + } + + if (!zchan->dtmf_off) { + zchan->dtmf_off = 50; + } + + memset(&zchan->tone_session, 0, sizeof(zchan->tone_session)); + teletone_init_session(&zchan->tone_session, 1024, NULL, NULL); + + zchan->tone_session.rate = 8000; + zchan->tone_session.duration = zchan->dtmf_on * (zchan->tone_session.rate / 1000); + zchan->tone_session.wait = zchan->dtmf_off * (zchan->tone_session.rate / 1000); + return ZAP_SUCCESS; +} + zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, void *obj) { assert(zchan != NULL); @@ -376,10 +414,32 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo } switch(command) { + case ZAP_COMMAND_SET_CODEC: + { + if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_CODECS)) { + zchan->effective_codec = ZAP_COMMAND_OBJ_INT; + if (zchan->effective_codec == zchan->native_codec) { + zap_clear_flag(zchan, ZAP_CHANNEL_TRANSCODE); + } else { + zap_set_flag(zchan, ZAP_CHANNEL_TRANSCODE); + } + return ZAP_SUCCESS; + } + } + break; + + case ZAP_COMMAND_GET_CODEC: + { + if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_CODECS)) { + ZAP_COMMAND_OBJ_INT = zchan->effective_codec; + return ZAP_SUCCESS; + } + } + break; case ZAP_COMMAND_ENABLE_TONE_DETECT: { /* if they don't have thier own, use ours */ - if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF_DETECT)) { + if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF)) { zap_tone_type_t tt = ZAP_COMMAND_OBJ_INT; if (tt == ZAP_TONE_DTMF) { teletone_dtmf_detect_init (&zchan->dtmf_detect, 8000); @@ -395,7 +455,7 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo break; case ZAP_COMMAND_DISABLE_TONE_DETECT: { - if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF_DETECT)) { + if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF)) { zap_tone_type_t tt = ZAP_COMMAND_OBJ_INT; if (tt == ZAP_TONE_DTMF) { teletone_dtmf_detect_init (&zchan->dtmf_detect, 8000); @@ -408,6 +468,74 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo } } } + case ZAP_COMMAND_GET_DTMF_ON_PERIOD: + { + if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF)) { + ZAP_COMMAND_OBJ_INT = zchan->dtmf_on; + return ZAP_SUCCESS; + } + } + break; + case ZAP_COMMAND_GET_DTMF_OFF_PERIOD: + { + if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF)) { + ZAP_COMMAND_OBJ_INT = zchan->dtmf_on; + return ZAP_SUCCESS; + } + } + break; + case ZAP_COMMAND_SET_DTMF_ON_PERIOD: + { + if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF)) { + int val = ZAP_COMMAND_OBJ_INT; + if (val > 10 && val < 1000) { + zchan->dtmf_on = val; + return ZAP_SUCCESS; + } else { + snprintf(zchan->last_error, sizeof(zchan->last_error), "invalid value %d range 10-1000", val); + return ZAP_FAIL; + } + } + } + break; + case ZAP_COMMAND_SET_DTMF_OFF_PERIOD: + { + if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF)) { + int val = ZAP_COMMAND_OBJ_INT; + if (val > 10 && val < 1000) { + zchan->dtmf_off = val; + return ZAP_SUCCESS; + } else { + snprintf(zchan->last_error, sizeof(zchan->last_error), "invalid value %d range 10-1000", val); + return ZAP_FAIL; + } + } + } + break; + case ZAP_COMMAND_SEND_DTMF: + { + if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF)) { + zap_status_t status; + char *cur; + char *digits = ZAP_COMMAND_OBJ_CHAR_P; + if (!zchan->dtmf_buffer) { + if ((status = zchan_activate_dtmf_buffer(zchan)) != ZAP_SUCCESS) { + return status; + } + } + zap_log(ZAP_LOG_DEBUG, "Adding DTMF SEQ [%s]\n", digits); + + for (cur = digits; *cur; cur++) { + int wrote = 0; + if ((wrote = teletone_mux_tones(&zchan->tone_session, &zchan->tone_session.TONES[(int)*cur]))) { + zap_buffer_write(zchan->dtmf_buffer, zchan->tone_session.buffer, wrote * 2); + } + } + + zchan->skip_read_frames = 200; + return ZAP_SUCCESS; + } + } break; default: break; @@ -422,7 +550,7 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo } -zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t *flags, unsigned to) +zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t *flags, uint32_t to) { assert(zchan != NULL); assert(zchan->zint != NULL); @@ -446,7 +574,7 @@ ZINT_CODEC_FUNCTION(zint_slin2ulaw) { int16_t sln_buf[512] = {0}, *sln = sln_buf; uint8_t *lp = data; - unsigned i; + uint32_t i; zap_size_t len = *datalen; if (max > len) { @@ -470,7 +598,7 @@ ZINT_CODEC_FUNCTION(zint_ulaw2slin) { int16_t *sln = data; uint8_t law[1024] = {0}, *lp = law; - unsigned i; + uint32_t i; zap_size_t len = *datalen; if (max > len) { @@ -482,7 +610,7 @@ ZINT_CODEC_FUNCTION(zint_ulaw2slin) for(i = 0; i < max; i++) { *sln++ = ulaw_to_linear(*lp++); } - + *datalen = max * 2; return ZAP_SUCCESS; @@ -492,7 +620,7 @@ ZINT_CODEC_FUNCTION(zint_slin2alaw) { int16_t sln_buf[512] = {0}, *sln = sln_buf; uint8_t *lp = data; - unsigned i; + uint32_t i; zap_size_t len = *datalen; if (max > len) { @@ -516,7 +644,7 @@ ZINT_CODEC_FUNCTION(zint_alaw2slin) { int16_t *sln = data; uint8_t law[1024] = {0}, *lp = law; - unsigned i; + uint32_t i; zap_size_t len = *datalen; if (max > len) { @@ -537,7 +665,7 @@ ZINT_CODEC_FUNCTION(zint_alaw2slin) ZINT_CODEC_FUNCTION(zint_ulaw2alaw) { zap_size_t len = *datalen; - unsigned i; + uint32_t i; uint8_t *lp = data; if (max > len) { @@ -555,7 +683,7 @@ ZINT_CODEC_FUNCTION(zint_ulaw2alaw) ZINT_CODEC_FUNCTION(zint_alaw2ulaw) { zap_size_t len = *datalen; - unsigned i; + uint32_t i; uint8_t *lp = data; if (max > len) { @@ -594,7 +722,7 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data status = zchan->zint->read(zchan, data, datalen); - if (status == ZAP_SUCCESS && zchan->effective_codec != zchan->native_codec) { + if (status == ZAP_SUCCESS && zap_test_flag(zchan, ZAP_CHANNEL_TRANSCODE) && zchan->effective_codec != zchan->native_codec) { if (zchan->native_codec == ZAP_CODEC_ULAW && zchan->effective_codec == ZAP_CODEC_SLIN) { codec_func = zint_ulaw2slin; } else if (zchan->native_codec == ZAP_CODEC_ULAW && zchan->effective_codec == ZAP_CODEC_ALAW) { @@ -623,7 +751,7 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data slen = *datalen / 2; } else { zap_size_t len = *datalen; - unsigned i; + uint32_t i; uint8_t *lp = data; slen = max; @@ -679,8 +807,8 @@ zap_status_t zap_channel_write(zap_channel_t *zchan, void *data, zap_size_t *dat { zap_status_t status = ZAP_FAIL; zint_codec_t codec_func; - zap_size_t max = *datalen; - + zap_size_t dtmf_blen, max = *datalen; + assert(zchan != NULL); assert(zchan->zint != NULL); @@ -694,8 +822,7 @@ zap_status_t zap_channel_write(zap_channel_t *zchan, void *data, zap_size_t *dat return ZAP_FAIL; } - - if (zchan->effective_codec != zchan->native_codec) { + if (zap_test_flag(zchan, ZAP_CHANNEL_TRANSCODE) && zchan->effective_codec != zchan->native_codec) { if (zchan->native_codec == ZAP_CODEC_ULAW && zchan->effective_codec == ZAP_CODEC_SLIN) { codec_func = zint_slin2ulaw; } else if (zchan->native_codec == ZAP_CODEC_ULAW && zchan->effective_codec == ZAP_CODEC_ALAW) { @@ -714,6 +841,36 @@ zap_status_t zap_channel_write(zap_channel_t *zchan, void *data, zap_size_t *dat } } + if (zchan->dtmf_buffer && (dtmf_blen = zap_buffer_inuse(zchan->dtmf_buffer))) { + zap_size_t dlen = *datalen; + uint8_t auxbuf[1024]; + uint32_t len, br; + + if (zchan->native_codec != ZAP_CODEC_SLIN) { + dlen *= 2; + } + + len = dtmf_blen > dlen ? dlen : dtmf_blen; + + br = zap_buffer_read(zchan->dtmf_buffer, auxbuf, len); + + if (br < dlen) { + memset(auxbuf + br, 0, dlen - br); + } + + memcpy(data, auxbuf, dlen); + + if (zchan->native_codec != ZAP_CODEC_SLIN) { + if (zchan->native_codec == ZAP_CODEC_ULAW) { + *datalen = dlen; + zint_slin2ulaw(data, max, datalen); + } else if (zchan->native_codec == ZAP_CODEC_ALAW) { + *datalen = dlen; + zint_slin2alaw(data, max, datalen); + } + } + } + status = zchan->zint->write(zchan, data, datalen); return status; @@ -723,7 +880,7 @@ zap_status_t zap_global_init(void) { zap_config_t cfg; char *var, *val; - unsigned configured = 0; + uint32_t configured = 0; zap_software_interface_t *zint; int modcount; @@ -801,7 +958,7 @@ zap_status_t zap_global_destroy(void) } -unsigned zap_separate_string(char *buf, char delim, char **array, int arraylen) +uint32_t zap_separate_string(char *buf, char delim, char **array, int arraylen) { int argc; char *ptr; diff --git a/libs/freetdm/src/zap_wanpipe.c b/libs/freetdm/src/zap_wanpipe.c index 0cfaa92e49..cc86622b57 100644 --- a/libs/freetdm/src/zap_wanpipe.c +++ b/libs/freetdm/src/zap_wanpipe.c @@ -354,20 +354,6 @@ static ZINT_COMMAND_FUNCTION(wanpipe_command) err = wp_tdm_cmd_exec(zchan, &tdm_api); } break; - - case ZAP_COMMAND_SET_CODEC: - { - zchan->effective_codec = ZAP_COMMAND_OBJ_INT; - err = 0; - } - break; - - case ZAP_COMMAND_GET_CODEC: - { - ZAP_COMMAND_OBJ_INT = zchan->effective_codec; - err = 0; - } - break; default: break; };