From b4fa2bdd33ef292c429c9da9d58d2ad7cdb51305 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthony.minessale@gmail.com>
Date: Fri, 25 May 2007 23:39:01 +0000
Subject: [PATCH] update

git-svn-id: http://svn.openzap.org/svn/openzap/trunk@153 a93c3328-9c30-0410-af19-c9cd2b2d52af
---
 libs/freetdm/src/include/openzap.h   | 12 +++-
 libs/freetdm/src/include/zap_types.h |  5 +-
 libs/freetdm/src/zap_analog.c        | 43 ++++++++----
 libs/freetdm/src/zap_io.c            | 97 ++++++++++++++++++++++------
 4 files changed, 122 insertions(+), 35 deletions(-)

diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h
index f1a2c93854..b3e0f51a4a 100644
--- a/libs/freetdm/src/include/openzap.h
+++ b/libs/freetdm/src/include/openzap.h
@@ -188,8 +188,8 @@
 
 #define zap_set_state_locked(obj, s) assert(obj->mutex != NULL); zap_mutex_lock(obj->mutex);\
 	zap_log(ZAP_LOG_DEBUG, "Changing state from %s to %s\n", zap_channel_state2str(obj->state), zap_channel_state2str(s));\
-	zap_set_flag(obj, ZAP_CHANNEL_STATE_CHANGE);\
-	obj->last_state = obj->state; obj->state = s; zap_mutex_unlock(obj->mutex);
+	zap_channel_set_state(obj, s);
+
 
 #define zap_is_dtmf(key)  ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119)
 
@@ -319,7 +319,7 @@ struct zap_io_interface {
 	struct zap_span spans[ZAP_MAX_SPANS_INTERFACE];
 };
 
-
+zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t state);
 zap_status_t zap_span_load_tones(zap_span_t *span, char *mapname);
 zap_size_t zap_channel_dequeue_dtmf(zap_channel_t *zchan, char *dtmf, zap_size_t len);
 zap_status_t zap_channel_queue_dtmf(zap_channel_t *zchan, const char *dtmf);
@@ -346,6 +346,12 @@ void zap_global_set_logger(zap_logger_t logger);
 void zap_global_set_default_logger(int level);
 uint32_t zap_separate_string(char *buf, char delim, char **array, int arraylen);
 void print_bits(uint8_t *b, int bl, char *buf, int blen, int e);
+ZIO_CODEC_FUNCTION(zio_slin2ulaw);
+ZIO_CODEC_FUNCTION(zio_ulaw2slin);
+ZIO_CODEC_FUNCTION(zio_slin2alaw);
+ZIO_CODEC_FUNCTION(zio_alaw2slin);
+ZIO_CODEC_FUNCTION(zio_ulaw2alaw);
+ZIO_CODEC_FUNCTION(zio_alaw2ulaw);
 
 
 #endif
diff --git a/libs/freetdm/src/include/zap_types.h b/libs/freetdm/src/include/zap_types.h
index 23bfaf9170..3801012105 100644
--- a/libs/freetdm/src/include/zap_types.h
+++ b/libs/freetdm/src/include/zap_types.h
@@ -100,13 +100,14 @@ typedef enum {
 	ZAP_SIGEVENT_STOP,
 	ZAP_SIGEVENT_TRANSFER,
 	ZAP_SIGEVENT_ANSWER,
+	ZAP_SIGEVENT_UP,
 	ZAP_SIGEVENT_PROGRESS,
 	ZAP_SIGEVENT_PROGRESS_MEDIA,
 	ZAP_SIGEVENT_NOTIFY,
 	ZAP_SIGEVENT_MISC,
 	ZAP_SIGEVENT_INVALID
 } zap_signal_event_t;
-#define SIGNAL_STRINGS "START", "STOP", "TRANSFER", "ANSWER", "PROGRESS", "PROGRESS_MEDIA", "NOTIFY", "MISC", "INVALID"
+#define SIGNAL_STRINGS "START", "STOP", "TRANSFER", "ANSWER", "UP", "PROGRESS", "PROGRESS_MEDIA", "NOTIFY", "MISC", "INVALID"
 ZAP_STR2ENUM_P(zap_str2zap_signal_event, zap_signal_event2str, zap_signal_event_t)
 
 typedef enum {
@@ -155,6 +156,8 @@ typedef enum {
 	ZAP_COMMAND_GET_INTERVAL,
 	ZAP_COMMAND_SET_CODEC,
 	ZAP_COMMAND_GET_CODEC,
+	ZAP_COMMAND_SET_NATIVE_CODEC,
+	ZAP_COMMAND_GET_NATIVE_CODEC,
 	ZAP_COMMAND_ENABLE_TONE_DETECT,
 	ZAP_COMMAND_DISABLE_TONE_DETECT,
 	ZAP_COMMAND_SEND_DTMF,
diff --git a/libs/freetdm/src/zap_analog.c b/libs/freetdm/src/zap_analog.c
index d4f80a1ff8..5852dd8a02 100644
--- a/libs/freetdm/src/zap_analog.c
+++ b/libs/freetdm/src/zap_analog.c
@@ -86,7 +86,6 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 	teletone_generation_session_t ts;
 	uint8_t frame[1024];
 	zap_size_t len, rlen;
-	zap_codec_t codec = ZAP_CODEC_SLIN, old_codec;
 	zap_tone_type_t tt = ZAP_TONE_DTMF;
 	char dtmf[128];
 	int dtmf_offset = 0;
@@ -112,19 +111,19 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 	zap_set_flag_locked(chan, ZAP_CHANNEL_INTHREAD);
 	teletone_init_session(&ts, 0, teletone_handler, dt_buffer);
 	ts.rate = 8000;
-	zap_channel_command(chan, ZAP_COMMAND_GET_CODEC, &old_codec);
+
 	zap_channel_command(chan, ZAP_COMMAND_GET_INTERVAL, &interval);
 	zap_buffer_set_loops(dt_buffer, -1);
 
 	while (zap_test_flag(chan, ZAP_CHANNEL_INTHREAD)) {
 		zap_wait_flag_t flags = ZAP_READ;
 		zap_size_t dlen = 0;
-
+		
 		len = sizeof(frame);
 		
 		elapsed += interval;
 		state_counter += interval;
-		
+
 		if (!zap_test_flag(chan, ZAP_CHANNEL_STATE_CHANGE)) {
 			switch(chan->state) {
 			case ZAP_CHANNEL_STATE_DIALTONE:
@@ -144,6 +143,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 			case ZAP_CHANNEL_STATE_UP:
 			case ZAP_CHANNEL_STATE_IDLE:
 				{
+
 					zap_sleep(interval);
 					continue;
 				}
@@ -153,13 +153,14 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 
 			}
 		} else {
+
 			zap_clear_flag_locked(chan, ZAP_CHANNEL_STATE_CHANGE);
 			switch(chan->state) {
 			case ZAP_CHANNEL_STATE_UP:
 				{
-					zap_channel_command(chan, ZAP_COMMAND_SET_CODEC, &old_codec);
-					sig.event_id = ZAP_SIGEVENT_ANSWER;
+					sig.event_id = ZAP_SIGEVENT_UP;
 					data->sig_cb(&sig);
+					
 					continue;
 				}
 				break;
@@ -173,6 +174,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 					sig.span = chan->span;
 					zap_copy_string(sig.dnis, dtmf, sizeof(sig.dnis));
 					data->sig_cb(&sig);
+					continue;
 				}
 				break;
 			case ZAP_CHANNEL_STATE_DOWN:
@@ -221,7 +223,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 			state_counter = 0;
 		}
 		
-		
+
 		if ((dlen = zap_channel_dequeue_dtmf(chan, dtmf + dtmf_offset, sizeof(dtmf) - strlen(dtmf)))) {
 			if (chan->state == ZAP_CHANNEL_STATE_DIALTONE || chan->state == ZAP_CHANNEL_STATE_COLLECT) {
 				zap_log(ZAP_LOG_DEBUG, "DTMF %s\n", dtmf + dtmf_offset);
@@ -245,11 +247,30 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 		
 		if (flags & ZAP_READ) {
 			if (zap_channel_read(chan, frame, &len) == ZAP_SUCCESS) {
+				if (chan->effective_codec != ZAP_CODEC_SLIN) {
+					len *= 2;
+				}
 				rlen = zap_buffer_read_loop(dt_buffer, frame, len);
-				if (indicate) {
-					if (chan->effective_codec != codec) {
-						zap_channel_command(chan, ZAP_COMMAND_SET_CODEC, &codec);
+				
+				if (indicate) {		
+					zio_codec_t codec_func = NULL;
+					zap_status_t status;
+					
+					if (chan->effective_codec != ZAP_CODEC_SLIN) {
+						if (chan->native_codec == ZAP_CODEC_ULAW) {
+							codec_func = zio_slin2ulaw;
+						} else if (chan->native_codec == ZAP_CODEC_ALAW) {
+							codec_func = zio_slin2alaw;
+						}
+						
+						if (codec_func) {
+							status = codec_func(frame, sizeof(frame), &rlen);
+						} else {
+							snprintf(chan->last_error, sizeof(chan->last_error), "codec error!");
+							status = ZAP_FAIL;
+						}
 					}
+
 					zap_channel_write(chan, frame, &rlen);
 				}
 			} else {
@@ -264,7 +285,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 	closed_chan = chan;
 	zap_channel_close(&chan);
 
-	zap_channel_command(closed_chan, ZAP_COMMAND_SET_CODEC, &old_codec);
+	zap_channel_command(closed_chan, ZAP_COMMAND_SET_NATIVE_CODEC, NULL);
 
 	if (ts.buffer) {
 		teletone_destroy_session(&ts);
diff --git a/libs/freetdm/src/zap_io.c b/libs/freetdm/src/zap_io.c
index 61c73bb966..a651b624a2 100644
--- a/libs/freetdm/src/zap_io.c
+++ b/libs/freetdm/src/zap_io.c
@@ -370,6 +370,39 @@ zap_status_t zap_channel_set_event_callback(zap_channel_t *zchan, zio_event_cb_t
 	return ZAP_SUCCESS;
 }
 
+
+zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t state)
+{
+	int ok = 1;
+
+	zap_mutex_unlock(zchan->mutex);
+
+	if (zchan->state == ZAP_CHANNEL_STATE_DOWN) {
+
+		switch(state) {
+		case ZAP_CHANNEL_STATE_BUSY:
+			ok = 0;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (state == zchan->state) {
+		ok = 0;
+	}
+
+	if (ok) {
+		zap_set_flag(zchan, ZAP_CHANNEL_STATE_CHANGE);	
+		zchan->last_state = zchan->state; 
+		zchan->state = state;
+	}
+
+	zap_mutex_unlock(zchan->mutex);
+
+	return ok ? ZAP_SUCCESS : ZAP_FAIL;
+}
+
 zap_status_t zap_channel_open_any(const char *name, uint32_t span_id, zap_direction_t direction, zap_channel_t **zchan)
 {
 	zap_io_interface_t *zio;
@@ -660,6 +693,17 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo
 		}
 		break;
 
+	case ZAP_COMMAND_SET_NATIVE_CODEC:
+		{
+			if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_CODECS)) {
+				zchan->effective_codec = zchan->native_codec;
+				zap_clear_flag(zchan, ZAP_CHANNEL_TRANSCODE);
+				zchan->packet_len = zchan->native_interval * (zchan->effective_codec == ZAP_CODEC_SLIN ? 16 : 8);
+				GOTO_STATUS(done, ZAP_SUCCESS);
+			}
+		}
+		break;
+
 	case ZAP_COMMAND_GET_CODEC: 
 		{
 			if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_CODECS)) {
@@ -668,6 +712,14 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo
 			}
 		}
 		break;
+	case ZAP_COMMAND_GET_NATIVE_CODEC: 
+		{
+			if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_CODECS)) {
+				ZAP_COMMAND_OBJ_INT = zchan->native_codec;
+				GOTO_STATUS(done, ZAP_SUCCESS);
+			}
+		}
+		break;
 	case ZAP_COMMAND_ENABLE_TONE_DETECT:
 		{
 			/* if they don't have thier own, use ours */
@@ -937,15 +989,17 @@ ZIO_CODEC_FUNCTION(zio_alaw2ulaw)
 
 zap_size_t zap_channel_dequeue_dtmf(zap_channel_t *zchan, char *dtmf, zap_size_t len)
 {
-	zap_size_t bytes;
+	zap_size_t bytes = 0;
 
 	assert(zchan != NULL);
 
-	zap_mutex_lock(zchan->mutex);
-	if ((bytes = zap_buffer_read(zchan->digit_buffer, dtmf, len)) > 0) {
-		*(dtmf + bytes) = '\0';
+	if (zap_buffer_inuse(zchan->digit_buffer)) {
+		zap_mutex_lock(zchan->mutex);
+		if ((bytes = zap_buffer_read(zchan->digit_buffer, dtmf, len)) > 0) {
+			*(dtmf + bytes) = '\0';
+		}
+		zap_mutex_unlock(zchan->mutex);
 	}
-	zap_mutex_unlock(zchan->mutex);
 
 	return bytes;
 }
@@ -1027,8 +1081,9 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data
 	}
 
 	if (zap_test_flag(zchan, ZAP_CHANNEL_DTMF_DETECT)) {
-		int16_t sln_buf[1024], *sln = sln_buf;
-		zap_size_t slen;
+		uint8_t sln_buf[2048] = {0};
+		int16_t *sln;
+		zap_size_t slen = 0;
 		char digit_str[80] = "";
 
 		if (zchan->effective_codec == ZAP_CODEC_SLIN) {
@@ -1038,23 +1093,25 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data
 			zap_size_t len = *datalen;
 			uint32_t i;
 			uint8_t *lp = data;
-			slen = max;
+
+			slen = sizeof(sln_buf);
+			if (len > slen) {
+				len = slen;
+			}
 			
-			if (slen > len) {
-				slen = len;
-			}
-
-			if (zchan->effective_codec == ZAP_CODEC_ULAW) {
-				for(i = 0; i < slen; i++) {
+			sln = (int16_t *) sln_buf;
+			for(i = 0; i < len; i++) {
+				if (zchan->effective_codec == ZAP_CODEC_ULAW) {
 					*sln++ = ulaw_to_linear(*lp++);
-				} 
-			} else if (zchan->effective_codec == ZAP_CODEC_ALAW) {
-				for(i = 0; i < slen; i++) {
+				} else if (zchan->effective_codec == ZAP_CODEC_ALAW) {
 					*sln++ = alaw_to_linear(*lp++);
-				} 
+				} else {
+					snprintf(zchan->last_error, sizeof(zchan->last_error), "codec error!");
+					return ZAP_FAIL;
+				}
 			}
-
-			sln = sln_buf;
+			sln = (int16_t *) sln_buf;
+			slen = len;
 		}
 
 		teletone_dtmf_detect(&zchan->dtmf_detect, sln, (int)slen);