From 9fd18e7e1a2b1776efb5226f4a6a5cb104980906 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthony.minessale@gmail.com>
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/openzap/src/include/openzap.h   | 177 +++-------------------
 libs/openzap/src/include/zap_types.h | 196 +++++++++++++++++++++++++
 libs/openzap/src/openzap.c           | 211 +++++++++++++++++++++++----
 libs/openzap/src/zap_wanpipe.c       |  14 --
 4 files changed, 398 insertions(+), 200 deletions(-)
 create mode 100644 libs/openzap/src/include/zap_types.h

diff --git a/libs/openzap/src/include/openzap.h b/libs/openzap/src/include/openzap.h
index 67db68761a..c6e4e79343 100644
--- a/libs/openzap/src/include/openzap.h
+++ b/libs/openzap/src/include/openzap.h
@@ -78,10 +78,12 @@
 #include <strings.h>
 #endif
 #include <assert.h>
+#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 <windows.h>
-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/openzap/src/include/zap_types.h b/libs/openzap/src/include/zap_types.h
new file mode 100644
index 0000000000..b8613e613b
--- /dev/null
+++ b/libs/openzap/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 <windows.h>
+typedef HANDLE zap_socket_t;
+#else
+#include <stdint.h>
+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/openzap/src/openzap.c b/libs/openzap/src/openzap.c
index 1e215cf785..37a39c71cf 100644
--- a/libs/openzap/src/openzap.c
+++ b/libs/openzap/src/openzap.c
@@ -31,7 +31,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-
 #include "openzap.h"
 #include <stdarg.h>
 #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/openzap/src/zap_wanpipe.c b/libs/openzap/src/zap_wanpipe.c
index 0cfaa92e49..cc86622b57 100644
--- a/libs/openzap/src/zap_wanpipe.c
+++ b/libs/openzap/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;
 	};