diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h index 8235d30846..cb7e4178be 100644 --- a/libs/freetdm/src/include/openzap.h +++ b/libs/freetdm/src/include/openzap.h @@ -74,6 +74,39 @@ #pragma warning(disable:4706) #endif +#define ZAP_ENUM_NAMES(_NAME, _STRINGS) static char * _NAME [] = { _STRINGS , NULL }; +#define ZAP_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) _TYPE _FUNC1 (char *name); char * _FUNC2 (_TYPE type); +#define ZAP_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \ + _TYPE _FUNC1 (char *name) \ + { \ + int i; \ + _TYPE t = _MAX ; \ + \ + for (i = 0; i < _MAX ; i++) { \ + if (!strcasecmp(name, _STRINGS[i])) { \ + t = (_TYPE) i; \ + break; \ + } \ + } \ + \ + return t; \ + } \ + char * _FUNC2 (_TYPE type) \ + { \ + if (type > _MAX) { \ + type = _MAX; \ + } \ + return _STRINGS[(int)type]; \ + } \ + +#define zap_true(expr) \ + (expr && ( !strcasecmp(expr, "yes") || \ + !strcasecmp(expr, "on") || \ + !strcasecmp(expr, "true") || \ + !strcasecmp(expr, "enabled") || \ + !strcasecmp(expr, "active") || \ + atoi(expr))) ? 1 : 0 + #ifndef WIN32 #include #include @@ -108,14 +141,6 @@ #define GOTO_STATUS(label,st) status = st; goto label ; -#define zap_true(expr)\ - (expr && ( !strcasecmp(expr, "yes") ||\ - !strcasecmp(expr, "on") ||\ - !strcasecmp(expr, "true") ||\ - !strcasecmp(expr, "enabled") ||\ - !strcasecmp(expr, "active") ||\ - atoi(expr))) ? 1 : 0 - #define zap_copy_string(x,y,z) strncpy(x, y, z - 1) @@ -138,10 +163,10 @@ */ #define zap_set_flag(obj, flag) (obj)->flags |= (flag) -#define zap_set_flag_locked(obj, flag) assert(obj->mutex != NULL);\ -zap_mutex_lock(obj->mutex);\ -(obj)->flags |= (flag);\ -zap_mutex_unlock(obj->mutex); +#define zap_set_flag_locked(obj, flag) assert(obj->mutex != NULL); \ + zap_mutex_lock(obj->mutex); \ + (obj)->flags |= (flag); \ + zap_mutex_unlock(obj->mutex); /*! \brief Clear a flag on an arbitrary object while locked @@ -248,6 +273,7 @@ struct zap_span { struct zap_analog_data *analog_data; zap_event_t event_header; char last_error[256]; + char tone_map[ZAP_TONEMAP_INVALID+1][ZAP_TONEMAP_LEN]; zap_channel_t channels[ZAP_MAX_CHANNELS_SPAN]; }; @@ -269,13 +295,11 @@ struct zap_io_interface { struct zap_span spans[ZAP_MAX_SPANS_INTERFACE]; }; + +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); zap_time_t zap_current_time_in_ms(void); -zap_oob_event_t str2zap_oob_signal(char *name); -char *zap_oob_signal2str(zap_oob_event_t type); -zap_trunk_type_t str2zap_trunk_type(char *name); -char *zap_trunk_type2str(zap_trunk_type_t type); zap_status_t zap_span_poll_event(zap_span_t *span, uint32_t ms); zap_status_t zap_span_next_event(zap_span_t *span, zap_event_t **event); zap_status_t zap_span_find(const char *name, uint32_t id, zap_span_t **span); diff --git a/libs/freetdm/src/include/zap_analog.h b/libs/freetdm/src/include/zap_analog.h index 8c12797bf2..ff0919877d 100644 --- a/libs/freetdm/src/include/zap_analog.h +++ b/libs/freetdm/src/include/zap_analog.h @@ -43,6 +43,5 @@ typedef enum { typedef struct zap_analog_data zap_analog_data_t; zap_status_t zap_analog_start(zap_span_t *span); -zap_status_t zap_analog_configure_span(zap_span_t *span, zio_signal_cb_t sig_cb); - +zap_status_t zap_analog_configure_span(zap_span_t *span, char *tonemap, zio_signal_cb_t sig_cb); #endif diff --git a/libs/freetdm/src/include/zap_types.h b/libs/freetdm/src/include/zap_types.h index 1c609a16d6..9fafa28d65 100644 --- a/libs/freetdm/src/include/zap_types.h +++ b/libs/freetdm/src/include/zap_types.h @@ -51,7 +51,18 @@ struct zap_io_interface; #define ZAP_COMMAND_OBJ_INT *((int *)obj) #define ZAP_COMMAND_OBJ_CHAR_P (char *)obj -typedef uint64_t zap_time_t; +typedef uint64_t zap_time_t; + +#define ZAP_TONEMAP_LEN 128 +typedef enum { + ZAP_TONEMAP_DIAL, + ZAP_TONEMAP_RING, + ZAP_TONEMAP_BUSY, + ZAP_TONEMAP_ATTN, + ZAP_TONEMAP_INVALID +} zap_tonemap_t; +#define TONEMAP_STRINGS "DIAL", "RING", "BUSY", "ATTN", "INVALID" +ZAP_STR2ENUM_P(zap_str2zap_tonemap, zap_tonemap2str, zap_tonemap_t) typedef enum { ZAP_TRUNK_E1, @@ -60,6 +71,20 @@ typedef enum { ZAP_TRUNK_BRI, ZAP_TRUNK_NONE } zap_trunk_type_t; +#define TRUNK_STRINGS "E1", "T1", "J1", "BRI", "NONE" +ZAP_STR2ENUM_P(zap_str2zap_trunk_type, zap_trunk_type2str, zap_trunk_type_t) + +typedef enum { + ZAP_OOB_DTMF, ZAP_OOB_ONHOOK, + ZAP_OOB_OFFHOOK, + ZAP_OOB_WINK, + ZAP_OOB_FLASH, + ZAP_OOB_RING_START, + ZAP_OOB_RING_STOP, + ZAP_OOB_INVALID +} zap_oob_event_t; +#define OOB_STRINGS "DTMF", "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "INVALID" +ZAP_STR2ENUM_P(zap_str2zap_oob_event, zap_oob_event2str, zap_oob_event_t) typedef enum { ZAP_SIGTYPE_NONE, @@ -177,16 +202,6 @@ typedef enum { ZAP_CHANNEL_FLASH = (1 << 10) } zap_channel_flag_t; -typedef enum { - ZAP_OOB_DTMF, - ZAP_OOB_ONHOOK, - ZAP_OOB_OFFHOOK, - ZAP_OOB_WINK, - ZAP_OOB_FLASH, - ZAP_OOB_RING_START, - ZAP_OOB_RING_STOP, - ZAP_OOB_INVALID -} zap_oob_event_t; typedef struct zap_channel zap_channel_t; typedef struct zap_event zap_event_t; diff --git a/libs/freetdm/src/testanalog.c b/libs/freetdm/src/testanalog.c index 7254bf455e..0bec2444b1 100644 --- a/libs/freetdm/src/testanalog.c +++ b/libs/freetdm/src/testanalog.c @@ -24,7 +24,7 @@ int main(int argc, char *argv[]) } - zap_analog_configure_span(span, on_signal); + zap_analog_configure_span(span, "us", on_signal); zap_analog_start(span); while(zap_test_flag(span->analog_data, ZAP_ANALOG_RUNNING)) { diff --git a/libs/freetdm/src/zap_analog.c b/libs/freetdm/src/zap_analog.c index 1021dbae27..0029430615 100644 --- a/libs/freetdm/src/zap_analog.c +++ b/libs/freetdm/src/zap_analog.c @@ -34,17 +34,19 @@ #include "openzap.h" #include "zap_analog.h" -zap_status_t zap_analog_configure_span(zap_span_t *span, zio_signal_cb_t sig_cb) +zap_status_t zap_analog_configure_span(zap_span_t *span, char *tonemap, zio_signal_cb_t sig_cb) { + if (span->signal_type) { snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling."); return ZAP_FAIL; } - + span->analog_data = malloc(sizeof(*span->analog_data)); assert(span->analog_data != NULL); memset(span->analog_data, 0, sizeof(*span->analog_data)); span->signal_type = ZAP_SIGTYPE_ANALOG; + zap_span_load_tones(span, tonemap); return ZAP_SUCCESS; @@ -60,7 +62,6 @@ static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map } wrote = teletone_mux_tones(ts, map); zap_buffer_write(dt_buffer, ts->buffer, wrote * 2); - printf("add %d\n", wrote * 2); return 0; } @@ -72,17 +73,18 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) uint8_t frame[1024]; zap_size_t len, rlen; zap_codec_t codec = ZAP_CODEC_SLIN, old_codec; - char *tones[] = { "%(1000,0,350,440)", - "%(500,500,480,620)", - "v=2000;%(100,100,1400,2060,2450,2600)", - NULL }; - + char *tones[4] = {0}; time_t start; int isbz = 0; int wtime = 10; zap_tone_type_t tt = ZAP_TONE_DTMF; int play_tones = 1; + + tones[0] = chan->span->tone_map[ZAP_TONEMAP_DIAL]; + tones[1] = chan->span->tone_map[ZAP_TONEMAP_BUSY]; + tones[2] = chan->span->tone_map[ZAP_TONEMAP_ATTN]; + zap_log(ZAP_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n"); if (zap_channel_open_chan(chan) != ZAP_SUCCESS) { @@ -96,16 +98,16 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) if (zap_channel_command(chan, ZAP_COMMAND_ENABLE_TONE_DETECT, &tt) != ZAP_SUCCESS) { goto done; } - /*zap_channel_set_event_callback(chan, my_zap_event_handler);*/ - zap_set_flag_locked(chan, ZAP_CHANNEL_INTHREAD); zap_set_state_locked(chan, ZAP_CHANNEL_STATE_DIALTONE); teletone_init_session(&ts, 0, teletone_handler, dt_buffer); - ts.rate = 8000; +#if 0 ts.debug = 1; ts.debug_stream = stdout; +#endif + ts.rate = 8000; teletone_run(&ts, tones[isbz++]); zap_channel_command(chan, ZAP_COMMAND_GET_CODEC, &old_codec); zap_channel_command(chan, ZAP_COMMAND_SET_CODEC, &codec); @@ -113,8 +115,6 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) time(&start); - - while (chan->state >= ZAP_CHANNEL_STATE_DIALTONE && zap_test_flag(chan, ZAP_CHANNEL_INTHREAD)) { zap_wait_flag_t flags = ZAP_READ; char dtmf[128]; @@ -167,7 +167,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) static zap_status_t process_event(zap_span_t *span, zap_event_t *event) { - zap_log(ZAP_LOG_DEBUG, "EVENT [%s][%d:%d]\n", zap_oob_signal2str(event->enum_id), event->channel->span_id, event->channel->chan_id); + zap_log(ZAP_LOG_DEBUG, "EVENT [%s][%d:%d]\n", zap_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id); switch(event->enum_id) { case ZAP_OOB_ONHOOK: diff --git a/libs/freetdm/src/zap_io.c b/libs/freetdm/src/zap_io.c index f0e382f2e6..71014be2bc 100644 --- a/libs/freetdm/src/zap_io.c +++ b/libs/freetdm/src/zap_io.c @@ -76,85 +76,15 @@ static struct { } globals; -static char *TRUNK_TYPE_NAMES[] = { - "E1", - "T1", - "J1", - "BRI", - "NONE", - NULL -}; +/* enum lookup funcs */ +ZAP_ENUM_NAMES(TONEMAP_NAMES, TONEMAP_STRINGS) +ZAP_STR2ENUM(zap_str2zap_tonemap, zap_tonemap2str, zap_tonemap_t, TONEMAP_NAMES, ZAP_TONEMAP_INVALID) -static char *OOB_NAMES[] = { - "ZAP_OOB_DTMF", - "ZAP_OOB_ONHOOK", - "ZAP_OOB_OFFHOOK", - "WINK", - "FLASH", - "ZAP_OOB_RING_START", - "ZAP_OOB_RING_STOP", - "INVALID", - NULL -}; +ZAP_ENUM_NAMES(OOB_NAMES, OOB_STRINGS) +ZAP_STR2ENUM(zap_str2zap_oob_event, zap_oob_event2str, zap_oob_event_t, OOB_NAMES, ZAP_OOB_INVALID) -zap_oob_event_t str2zap_oob_signal(char *name) -{ - int i; - zap_trunk_type_t t = ZAP_OOB_INVALID; - - for (i = 0; i < ZAP_OOB_INVALID; i++) { - if (!strcasecmp(name, OOB_NAMES[i])) { - t = (zap_oob_event_t) i; - break; - } - } - - return t; -} - -char *zap_oob_signal2str(zap_oob_event_t type) -{ - if (type > ZAP_OOB_INVALID) { - type = ZAP_OOB_INVALID; - } - return OOB_NAMES[(int)type]; -} - -static char *LEVEL_NAMES[] = { - "EMERG", - "ALERT", - "CRIT", - "ERROR", - "WARNING", - "NOTICE", - "INFO", - "DEBUG", - NULL -}; - - -zap_trunk_type_t str2zap_trunk_type(char *name) -{ - int i; - zap_trunk_type_t t = ZAP_TRUNK_NONE; - - for (i = 0; i < ZAP_TRUNK_NONE; i++) { - if (!strcasecmp(name, TRUNK_TYPE_NAMES[i])) { - t = (zap_trunk_type_t) i; - break; - } - } - - return t; -} - -char *zap_trunk_type2str(zap_trunk_type_t type) -{ - if (type > ZAP_TRUNK_NONE) { - type = ZAP_TRUNK_NONE; - } - return TRUNK_TYPE_NAMES[(int)type]; -} +ZAP_ENUM_NAMES(TRUNK_TYPE_NAMES, TRUNK_STRINGS) +ZAP_STR2ENUM(zap_str2zap_trunk_type, zap_trunk_type2str, zap_trunk_type_t, TRUNK_TYPE_NAMES, ZAP_TRUNK_NONE) static char *cut_path(char *in) @@ -180,6 +110,19 @@ static void null_logger(char *file, const char *func, int line, int level, char return; } + +static char *LEVEL_NAMES[] = { + "EMERG", + "ALERT", + "CRIT", + "ERROR", + "WARNING", + "NOTICE", + "INFO", + "DEBUG", + NULL +}; + static int zap_log_level = 7; static void default_logger(char *file, const char *func, int line, int level, char *fmt, ...) @@ -260,6 +203,10 @@ zap_status_t zap_span_create(zap_io_interface_t *zio, zap_span_t **span) new_span->span_id = zio->span_index; new_span->zio = zio; zap_mutex_create(&new_span->mutex); + zap_copy_string(new_span->tone_map[ZAP_TONEMAP_DIAL], "%(1000,0,350,440)", ZAP_TONEMAP_LEN); + zap_copy_string(new_span->tone_map[ZAP_TONEMAP_RING], "%(2000,4000,440,480)", ZAP_TONEMAP_LEN); + zap_copy_string(new_span->tone_map[ZAP_TONEMAP_BUSY], "%(500,500,480,620)", ZAP_TONEMAP_LEN); + zap_copy_string(new_span->tone_map[ZAP_TONEMAP_ATTN], "%(100,100,1400,2060,2450,2600)", ZAP_TONEMAP_LEN); *span = new_span; return ZAP_SUCCESS; } @@ -295,6 +242,39 @@ zap_status_t zap_span_close_all(zap_io_interface_t *zio) return i ? ZAP_SUCCESS : ZAP_FAIL; } +zap_status_t zap_span_load_tones(zap_span_t *span, char *mapname) +{ + zap_config_t cfg; + char *var, *val; + int x = 0; + + if (!zap_config_open_file(&cfg, "tones.conf")) { + snprintf(span->last_error, sizeof(span->last_error), "error loading tones."); + return ZAP_FAIL; + } + + while (zap_config_next_pair(&cfg, &var, &val)) { + if (!strcasecmp(cfg.category, mapname) && var && val) { + int index = zap_str2zap_tonemap(var); + if (index > ZAP_TONEMAP_INVALID) { + zap_log(ZAP_LOG_WARNING, "Unknown tone name %s\n", var); + } else { + zap_log(ZAP_LOG_DEBUG, "added tone [%s] = [%s] %d\n", var, val, index); + zap_copy_string(span->tone_map[index], val, sizeof(span->tone_map[index])); + x++; + } + } + } + + if (!x) { + snprintf(span->last_error, sizeof(span->last_error), "error loading tones."); + return ZAP_FAIL; + } + + return ZAP_SUCCESS; + +} + zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_chan_type_t type, zap_channel_t **chan) { if (span->chan_count < ZAP_MAX_CHANNELS_SPAN) { diff --git a/libs/freetdm/src/zap_wanpipe.c b/libs/freetdm/src/zap_wanpipe.c index 448bc146cd..81aeef82df 100644 --- a/libs/freetdm/src/zap_wanpipe.c +++ b/libs/freetdm/src/zap_wanpipe.c @@ -225,7 +225,7 @@ static ZIO_CONFIGURE_FUNCTION(wanpipe_configure) if (!strcasecmp(var, "enabled")) { zap_log(ZAP_LOG_WARNING, "'enabled' command ignored when it's not the first command in a [span]\n"); } else if (!strcasecmp(var, "trunk_type")) { - span->trunk_type = str2zap_trunk_type(val); + span->trunk_type = zap_str2zap_trunk_type(val); zap_log(ZAP_LOG_DEBUG, "setting trunk type to '%s'\n", zap_trunk_type2str(span->trunk_type)); } else if (!strcasecmp(var, "fxo-channel")) { configured += wp_configure_channel(&cfg, val, span, ZAP_CHAN_TYPE_FXO);