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
This commit is contained in:
Anthony Minessale 2007-05-19 04:07:48 +00:00
parent e21ca79927
commit 43e6b6fa23
4 changed files with 398 additions and 200 deletions

View File

@ -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

View File

@ -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

View File

@ -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) {
@ -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,7 +807,7 @@ 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;

View File

@ -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;
};