#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)
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);
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
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 {
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,
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;
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:
case ZAP_CHANNEL_STATE_UP:
case ZAP_CHANNEL_STATE_IDLE:
{
+
zap_sleep(interval);
continue;
}
}
} 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;
sig.span = chan->span;
zap_copy_string(sig.dnis, dtmf, sizeof(sig.dnis));
data->sig_cb(&sig);
+ continue;
}
break;
case ZAP_CHANNEL_STATE_DOWN:
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);
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 {
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);
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;
}
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)) {
}
}
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 */
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;
}
}
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) {
zap_size_t len = *datalen;
uint32_t i;
uint8_t *lp = data;
- slen = max;
-
- if (slen > len) {
- slen = len;
- }
- if (zchan->effective_codec == ZAP_CODEC_ULAW) {
- for(i = 0; i < slen; i++) {
+ slen = sizeof(sln_buf);
+ if (len > slen) {
+ len = slen;
+ }
+
+ 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);