Oh, you're right. I always forget to attach files ;-)
François On Wed, 24 Feb 2010 04:13:38 -0500, Michael Jerris wrote: where? On Feb 24, 2010, at 3:53 AM, François Legal wrote: Hello, Here comes the patch. The patch fixes the CID for France (and probably other european countries except maybe england where a specific TAS has to be used), both for incoming calls and call waiting cases. If anybody can try this patch with US hardware to verify the compatibility. I added a new parameter in openzap.conf (modem-type defaulting to FSK_BELL202) so that modulation can be specified in config. The patch also adds the MWI functionnality on FXS ports (that meant to also patch mod_voicemail), by using the MWI-Account parameter in directory set to something like "openzap/x/y". Please comment on this, if any modification need to be made. François
--- ./libs/openzap/src/.svn/text-base/zap_io.c.svn-base 2010-02-11 11:03:16.000000000 +0100 +++ ./libs/openzap/src/zap_io.c 2010-02-23 17:02:28.371058955 +0100 @@ -645,12 +645,13 @@ } if (zchan->token_count > 1) { - zap_fsk_modulator_init(&fsk_trans, FSK_BELL202, zchan->rate, fsk_data, db_level, 80, 5, 0, zchan_fsk_write_sample, zchan); + /*zap_fsk_modulator_init(&fsk_trans, FSK_V23_FORWARD_MODE2, zchan->rate, fsk_data, db_level, 80, 5, 0, zchan_fsk_write_sample, zchan);*/ + zap_fsk_modulator_init(&fsk_trans, zchan->span->modem_type, zchan->rate, fsk_data, db_level, 80, 5, 0, zchan_fsk_write_sample, zchan); zap_fsk_modulator_send_all((&fsk_trans)); } else { - zap_fsk_modulator_init(&fsk_trans, FSK_BELL202, zchan->rate, fsk_data, db_level, 180, 5, 300, zchan_fsk_write_sample, zchan); + /*zap_fsk_modulator_init(&fsk_trans, FSK_V23_FORWARD_MODE2, zchan->rate, fsk_data, db_level, 180, 5, 300, zchan_fsk_write_sample, zchan);*/ + zap_fsk_modulator_init(&fsk_trans, zchan->span->modem_type, zchan->rate, fsk_data, db_level, 180, 5, 300, zchan_fsk_write_sample, zchan); zap_fsk_modulator_send_all((&fsk_trans)); - zchan->buffer_delay = 3500 / zchan->effective_interval; } return ZAP_SUCCESS; @@ -868,6 +869,7 @@ case ZAP_CHANNEL_STATE_PROGRESS: case ZAP_CHANNEL_STATE_GET_CALLERID: case ZAP_CHANNEL_STATE_GENRING: + case ZAP_CHANNEL_STATE_MWI: ok = 1; break; default: @@ -1582,6 +1584,16 @@ zap_mutex_unlock(zchan->pre_buffer_mutex); } break; + + case ZAP_COMMAND_SET_MWI: + { + zchan->pre_buffer_size = ZAP_COMMAND_OBJ_INT; + + status = zap_channel_set_state(zchan, ZAP_CHANNEL_STATE_MWI, 1); + + GOTO_STATUS(done, status); + } + break; default: break; } @@ -1925,6 +1937,13 @@ } } + if (zchan->fds[1] > -1) { + if ((write(zchan->fds[1], auxbuf, dlen)) != dlen) { + snprintf(zchan->last_error, sizeof(zchan->last_error), "file write error!"); + return ZAP_FAIL; + } + } + return zchan->zio->write(zchan, auxbuf, &dlen); } @@ -2047,6 +2066,7 @@ if (zap_fsk_demod_feed(&zchan->fsk, sln, slen) != ZAP_SUCCESS) { zap_size_t type, mlen; char str[128], *sp; + char firstcaller[128] = { '*', '\0'}; while(zap_fsk_data_parse(&zchan->fsk, &type, &sp, &mlen) == ZAP_SUCCESS) { *(str+mlen) = '\0'; @@ -2091,9 +2111,29 @@ zap_set_string(zchan->caller_data.cid_date, str); } break; + case MDMF_FIRST_PHONE_NUM: + { + if (mlen > sizeof(firstcaller) - 2) { + mlen = sizeof(firstcaller) - 2; + } + zap_set_string(&firstcaller[1], str); + } + break; } } zap_channel_command(zchan, ZAP_COMMAND_DISABLE_CALLERID_DETECT, NULL); + if (! zap_strlen_zero(&firstcaller[1])) { + if ((strncmp("private", zchan->caller_data.ani.digits, sizeof ("private") - 1) == 0) || + (strncmp("unknown", zchan->caller_data.ani.digits, sizeof ("unknown") - 1) == 0)) { + zap_set_string(zchan->caller_data.ani.digits, firstcaller); + zap_set_string(zchan->caller_data.cid_name, "FWD "); + zap_copy_string((char *) (zchan->caller_data.cid_name + 4), & firstcaller[1], strlen(& firstcaller[1])); + } else if ((strncmp("private", zchan->caller_data.cid_name, sizeof ("private") - 1) == 0) || + (strncmp("unknown", zchan->caller_data.cid_name, sizeof ("unknown") - 1) == 0)) { + zap_set_string(zchan->caller_data.cid_name, "FWD "); + zap_copy_string((char *) (zchan->caller_data.cid_name + 4), & firstcaller[1], strlen(& firstcaller[1])); + } + } } } @@ -2410,6 +2450,9 @@ continue; } + /* Set default modem type for span */ + span->modem_type = FSK_BELL202; + zap_log(ZAP_LOG_DEBUG, "span %d [%s]=[%s]\n", span->span_id, var, val); if (!strcasecmp(var, "trunk_type")) { @@ -2490,6 +2533,14 @@ } else if (!strcasecmp(var, "dtmf_hangup")) { span->dtmf_hangup = strdup(val); span->dtmf_hangup_len = strlen(val); + } else if (!strcasecmp(var, "modem-type")) { + if (!strcasecmp(val, "FSK_V23_FORWARD_MODE1")) { + span->modem_type = FSK_V23_FORWARD_MODE1; + } else if (!strcasecmp(val, "FSK_V23_FORWARD_MODE2")) { + span->modem_type = FSK_V23_FORWARD_MODE2; + } else if (!strcasecmp(val, "FSK_V23_BACKWARD")) { + span->modem_type = FSK_V23_BACKWARD; + } } else { zap_log(ZAP_LOG_ERROR, "unknown span variable '%s'\n", var); } --- ./libs/openzap/src/ozmod/ozmod_analog/.svn/text-base/ozmod_analog.c.svn-base 2010-02-11 11:03:15.000000000 +0100 +++ ./libs/openzap/src/ozmod/ozmod_analog/ozmod_analog.c 2010-02-24 09:27:29.079058352 +0100 @@ -256,6 +256,52 @@ } /** + * \brief Sends message wainting indicator on an analog channel (FSK coded) + * \param zchan Channel to send caller id on + * \param state indicator value as follows : if bit 0x80 is set, light on indicator - bits 0x7F : amount of messages waiting + */ +static void send_mwi(zap_channel_t *zchan, int state) +{ + zap_fsk_data_state_t fsk_data; + uint8_t databuf[1024] = ""; + char time_str[9]; + struct tm tm; + time_t now; + char indicator; + char amount_messages; + + time(&now); +#ifdef WIN32 + _tzset(); + _localtime64_s(&tm, &now); +#else + localtime_r(&now, &tm); +#endif + strftime(time_str, sizeof(time_str), "%m%d%H%M", &tm); + + zap_fsk_data_init(&fsk_data, databuf, sizeof(databuf)); + zap_fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, (uint8_t *) time_str, 8); + + if (state & 0x80) { + indicator = 0xFF; + amount_messages = state & 0x7F; + } else { + indicator = 0; + amount_messages = state; + } + + zap_fsk_data_add_mdmf(&fsk_data, MDMF_MWI, (uint8_t *) & indicator, (uint8_t) sizeof (indicator)); + + zap_fsk_data_add_mdmf(&fsk_data, MDMF_AMOUNT_MESSAGES, (uint8_t *) & amount_messages, (uint8_t) sizeof (amount_messages)); + + fsk_data.buf[0] = ZAP_CID_TYPE_MWI; + + zap_fsk_data_add_checksum(&fsk_data); + + zap_channel_send_fsk_data(zchan, &fsk_data, -14); +} + +/** * \brief Main thread function for analog channel (outgoing call) * \param me Current thread * \param obj Channel to run in this thread @@ -275,6 +321,7 @@ uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000; zap_sigmsg_t sig; zap_status_t status; + int time = 0; zap_log(ZAP_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n"); @@ -346,7 +393,15 @@ break; case ZAP_CHANNEL_STATE_GENRING: { - if (state_counter > 60000) { + if (state_counter == 260) { + zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_OFF, NULL); + } else if (state_counter == 900) { + send_caller_id(zchan); + } else if (state_counter > 900 && !zap_buffer_inuse(zchan->fsk_buffer) && time == 0) { + time = state_counter + 400; + } else if (state_counter == time) { + zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_ON, NULL); + } else if (state_counter > 60000) { zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); } else if (!zchan->fsk_buffer || !zap_buffer_inuse(zchan->fsk_buffer)) { zap_sleep(interval); @@ -354,6 +409,18 @@ } } break; + case ZAP_CHANNEL_STATE_MWI: + { + if (state_counter == 400) { + zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_OFF, NULL); + } else if (state_counter == 1100) { + send_mwi(zchan, zchan->pre_buffer_size); + } else if (state_counter > 1200 && !zap_buffer_inuse(zchan->fsk_buffer)) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); + continue; + } + } + break; case ZAP_CHANNEL_STATE_DIALTONE: { if (!zap_test_flag(zchan, ZAP_CHANNEL_HOLD) && state_counter > 10000) { @@ -397,7 +464,15 @@ { int done = 0; - if (zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] == 1) { + if (state_counter == 760) { + ts.user_data = zchan->fsk_buffer; + teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_CAS]); + ts.user_data = dt_buffer; + } else if (state_counter == 1100) { + send_caller_id(zchan); + } else + + /*if (zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] == 1) { send_caller_id(zchan); zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]++; } else if (state_counter > 600 && !zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]) { @@ -405,7 +480,8 @@ zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]++; } else if (state_counter > 1000 && !zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]) { done = 1; - } else if (state_counter > 10000) { + } else*/ if (state_counter > 10000) { + /* if (zchan->fsk_buffer) { zap_buffer_zero(zchan->fsk_buffer); } else { @@ -414,7 +490,7 @@ ts.user_data = zchan->fsk_buffer; teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_SAS]); - ts.user_data = dt_buffer; + ts.user_data = dt_buffer;*/ done = 1; } @@ -533,7 +609,7 @@ ts.user_data = zchan->fsk_buffer; teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_SAS]); - teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_CAS]); + /*teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_CAS]);*/ ts.user_data = dt_buffer; } break; @@ -541,8 +617,8 @@ { zap_sigmsg_t sig; - send_caller_id(zchan); zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_ON, NULL); + time = 0; memset(&sig, 0, sizeof(sig)); sig.chan_id = zchan->chan_id; @@ -553,6 +629,17 @@ } break; + case ZAP_CHANNEL_STATE_MWI: + { + if (zchan->fsk_buffer) { + zap_buffer_zero(zchan->fsk_buffer); + } else { + zap_buffer_create(&zchan->fsk_buffer, 128, 128, 0); + } + + zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_ON, NULL); + } + break; case ZAP_CHANNEL_STATE_GET_CALLERID: { memset(&zchan->caller_data, 0, sizeof(zchan->caller_data)); @@ -671,6 +758,8 @@ zap_log(ZAP_LOG_ERROR, "No Digits to send!\n"); zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_BUSY); } else { + /* I seem to have some trouble when dialing as soon as dialtone is detected */ + usleep (400000); if (zap_channel_command(zchan, ZAP_COMMAND_SEND_DTMF, zchan->caller_data.ani.digits) != ZAP_SUCCESS) { zap_log(ZAP_LOG_ERROR, "Send Digits Failed [%s]\n", zchan->last_error); zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_BUSY); --- ./libs/openzap/src/include/.svn/text-base/openzap.h.svn-base 2010-02-11 11:03:16.000000000 +0100 +++ ./libs/openzap/src/include/openzap.h 2010-02-23 17:00:23.540058087 +0100 @@ -585,6 +585,7 @@ int suggest_chan_id; zap_state_map_t *state_map; struct zap_span *next; + fsk_modem_types_t modem_type; }; @@ -636,6 +637,7 @@ OZ_DECLARE(int) zap_fsk_demod_init(zap_fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize); OZ_DECLARE(zap_status_t) zap_fsk_data_init(zap_fsk_data_state_t *state, uint8_t *data, uint32_t datalen); OZ_DECLARE(zap_status_t) zap_fsk_data_add_mdmf(zap_fsk_data_state_t *state, zap_mdmf_type_t type, const uint8_t *data, uint32_t datalen); +OZ_DECLARE(zap_status_t) zap_fsk_data_add_mwi(zap_fsk_data_state_t *state, zap_mdmf_type_t type, const uint8_t *data, uint32_t datalen); OZ_DECLARE(zap_status_t) zap_fsk_data_add_checksum(zap_fsk_data_state_t *state); OZ_DECLARE(zap_status_t) zap_fsk_data_add_sdmf(zap_fsk_data_state_t *state, const char *date, char *number); OZ_DECLARE(zap_status_t) zap_channel_outgoing_call(zap_channel_t *zchan); --- ./src/include/.svn/text-base/zap_types.h.svn-base 2010-02-11 11:03:16.000000000 +0100 +++ ./src/include/zap_types.h 2010-02-17 14:34:58.427058956 +0100 @@ -81,7 +81,8 @@ typedef enum { ZAP_CID_TYPE_SDMF = 0x04, - ZAP_CID_TYPE_MDMF = 0x80 + ZAP_CID_TYPE_MDMF = 0x80, + ZAP_CID_TYPE_MWI = 0x82 } zap_cid_type_t; typedef enum { @@ -92,9 +93,16 @@ MDMF_PHONE_NAME = 7, MDMF_NO_NAME = 8, MDMF_ALT_ROUTE = 9, - MDMF_INVALID = 10 + MDMF_MWI = 11, + MDMF_MESSAGE_ID = 13, + MDMF_LAST_VM_FROM = 14, + MDMF_CALL_TYPE = 17, + MDMF_FIRST_PHONE_NUM = 18, + MDMF_AMOUNT_MESSAGES = 19, + MDMF_FWD_TYPE = 21, + MDMF_INVALID = 22 } zap_mdmf_type_t; -#define MDMF_STRINGS "X", "DATETIME", "PHONE_NUM", "DDN", "NO_NUM", "X", "X", "PHONE_NAME", "NO_NAME", "ALT_ROUTE", "INVALID" +#define MDMF_STRINGS "X", "DATETIME", "PHONE_NUM", "DDN", "NO_NUM", "X", "X", "PHONE_NAME", "NO_NAME", "ALT_ROUTE", "X", "MWI", "X", "MESSAGE_ID", "LAST_VM_FROM", "X", "X", "CALL_TYPE", "FIRST_PHONE_NUM", "AMOUNT_OF_MESSAGES", "X", "FWD_TYPE", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_mdmf_type, zap_mdmf_type2str, zap_mdmf_type_t) #define ZAP_TONEMAP_LEN 128 @@ -284,7 +292,8 @@ ZAP_COMMAND_FLUSH_RX_BUFFERS, ZAP_COMMAND_FLUSH_BUFFERS, ZAP_COMMAND_SET_PRE_BUFFER_SIZE, - ZAP_COMMAND_COUNT + ZAP_COMMAND_COUNT, + ZAP_COMMAND_SET_MWI } zap_command_t; typedef enum { @@ -316,7 +325,8 @@ ZAP_CHANNEL_FEATURE_CODECS = (1 << 2), ZAP_CHANNEL_FEATURE_INTERVAL = (1 << 3), ZAP_CHANNEL_FEATURE_CALLERID = (1 << 4), - ZAP_CHANNEL_FEATURE_PROGRESS = (1 << 5) + ZAP_CHANNEL_FEATURE_PROGRESS = (1 << 5), + ZAP_CHANNEL_FEATURE_FAX_DETECT = (1 << 6) } zap_channel_feature_t; typedef enum { @@ -341,11 +351,12 @@ ZAP_CHANNEL_STATE_CANCEL, ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_HANGUP_COMPLETE, + ZAP_CHANNEL_STATE_MWI, ZAP_CHANNEL_STATE_INVALID } zap_channel_state_t; #define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \ "RING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \ - "RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", "HANGUP", "HANGUP_COMPLETE", "INVALID" + "RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", "HANGUP", "HANGUP_COMPLETE", "MWI", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t) typedef enum { --- ./libs/openzap/mod_openzap/.svn/text-base/mod_openzap.c.svn-base 2010-02-11 11:03:16.000000000 +0100 +++ ./libs/openzap/mod_openzap/mod_openzap.c 2010-02-23 19:02:31.071059153 +0100 @@ -1901,6 +1901,95 @@ } +static switch_status_t zap_send_mwi (int span_no, int chan_no, int messages) +{ + zap_span_t *span; + zap_channel_t *chan = NULL; + + if ((span = SPAN_CONFIG[span_no].span) == NULL) { + zap_log(ZAP_LOG_ERROR, "invalid span %d\n", span_no); + return (ZAP_FAIL); + } + + if (chan_no > span->chan_count || span->channels[chan_no] == NULL) { + zap_log(ZAP_LOG_ERROR, "invalid channel %d:%d\n", span_no, chan_no); + return (ZAP_FAIL); + } + + while (span->channels[chan_no]->state != ZAP_CHANNEL_STATE_DOWN) { + sleep (2); + } + + sleep (2); + + zap_channel_open(span_no, chan_no, &chan); + zap_channel_outgoing_call(chan); + zap_channel_command(chan, ZAP_COMMAND_SET_MWI, &messages); + zap_channel_init(chan); + + return (ZAP_SUCCESS); +} + +static void mod_openzap_mwi_handler(switch_event_t *event) +{ + char *account, *amount; + char *seek_ptr, *end_ptr; + int span_no = 0; + int chan_no = 0; + int amount_new = 0; + int amount_saved = 0; + + switch_assert(event); + + if (event->event_id == SWITCH_EVENT_MESSAGE_WAITING) { + + if (!(account = switch_event_get_header(event, "mwi-message-account"))) { + zap_log(ZAP_LOG_ERROR, "Missing required Header 'MWI-Message-Account'\n"); + return; + } + + if (strncmp ("openzap/", account, sizeof("openzap/") - 1)) { + zap_log(ZAP_LOG_DEBUG, "The MWI-Account is not for openzap notification : %s\n", account); + return; + } + + if ((seek_ptr = strchr(account, '/')) == NULL) { + span_no = chan_no = 0; + } else if ((end_ptr = strchr (++seek_ptr, '/')) == NULL) { + span_no = atoi(seek_ptr); + chan_no = 0; + } else { + span_no = atoi(seek_ptr); + chan_no = atoi(++end_ptr); + } + + if (!(amount = switch_event_get_header(event, "mwi-voice-message"))) { + zap_log(ZAP_LOG_ERROR, "Missing required Header 'mwi-voice-message'\n"); + return; + } + + if ((seek_ptr = strchr(amount, '/')) == NULL) { + amount_new = atoi(amount); + } else { + amount_new = atoi(amount); + amount_saved = atoi(++seek_ptr); + } + + if (amount_new > 0) { + amount_new |= 0x80; + } else { + amount_new += amount_saved; + } + + zap_log(ZAP_LOG_DEBUG, "Sending MWI on [%d:%d] : 0x%X\n", span_no, chan_no, amount_new); + zap_send_mwi(span_no, chan_no, amount_new); + + } else { + zap_log(ZAP_LOG_ERROR, "Unexpected event %d for this handler\n", event->event_id); + } + +} + static uint32_t enable_analog_option(const char *str, uint32_t current_options) { if (!strcasecmp(str, "3-way")) { @@ -2720,7 +2809,8 @@ ); } -#define OZ_SYNTAX "list || dump <span_id> [<chan_id>] || q931_pcap <span_id> on|off [pcapfilename without suffix]" +#define OZ_SYNTAX "list || dump <span_id> [<chan_id>] || q931_pcap <span_id> on|off [pcapfilename without suffix]" \ + " || trace <span_id> <chan_id> in|out [filename] || mwi <span_id> <chan_id> <mwi data>" SWITCH_STANDARD_API(oz_function) { char *mycmd = NULL, *argv[10] = { 0 }; @@ -2909,6 +2999,79 @@ goto end; } + } else if (!strcasecmp(argv[0], "trace")) { + int32_t span_id = 0; + int32_t chan_id = 0; + zap_span_t *span; + zap_channel_t *chan; + const char *pcapfn = NULL; + char *tmp_path = NULL; + zap_command_t command; + + if (argc < 3) { + stream->write_function(stream, "-ERR Usage: oz trace <span_id> <chan_id> in|out <filename>\n"); + goto end; + } + span_id = atoi(argv[1]); + if (!(span_id && (span = SPAN_CONFIG[span_id].span))) { + stream->write_function(stream, "-ERR invalid span\n"); + goto end; + } + + chan_id = atoi(argv[2]); + if (!(chan_id && (chan = span->channels[chan_id]))) { + stream->write_function(stream, "-ERR invalid channel\n"); + goto end; + } + + if (strcasecmp(argv[3], "in")) { + command = ZAP_COMMAND_TRACE_INPUT; + } else { + if (strcasecmp(argv[3], "out")) { + command = ZAP_COMMAND_TRACE_OUTPUT; + } else { + stream->write_function(stream, "-ERR invalid recording direction\n"); + goto end; + } + } + + /*Look for a given file name or use default file name*/ + if (argc > 4) { + if(argv[4]){ + pcapfn=argv[4]; + } + } + else { + tmp_path=switch_mprintf("%s%szap-%1d-%1d-%s.dmp", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, span_id, chan_id, argv[3]); + } + if (zap_channel_command(chan, command, tmp_path) != ZAP_SUCCESS) { + zap_log(ZAP_LOG_ERROR, "Error couldn't enable trace!\n"); + goto end; + } else { + stream->write_function(stream, "+OK\n"); + } + + } else if (!strcasecmp(argv[0], "mwi")) { + int32_t span_id = 0; + int32_t chan_id = 0; + int32_t indicator = 0; + + if (argc < 4) { + stream->write_function(stream, "-ERR Usage: oz mwi <span_id> <chan_id> <0|1>\n"); + goto end; + } + span_id = atoi(argv[1]); + chan_id = atoi(argv[2]); + indicator = atoi(argv[3]); + + zap_log(ZAP_LOG_DEBUG, "Sending MWI on [%d:%d] : 0x%X\n", span_id, chan_id, indicator); + + if (zap_send_mwi(span_id, chan_id, indicator) == ZAP_SUCCESS) { + stream->write_function(stream, "+OK\n"); + } else { + stream->write_function(stream, "-ERR\n"); + } + } else { char *rply = zap_api_execute(cmd, NULL); @@ -2978,6 +3141,10 @@ openzap_endpoint_interface->io_routines = &openzap_io_routines; openzap_endpoint_interface->state_handler = &openzap_state_handlers; + if (switch_event_bind(openzap_endpoint_interface->interface_name, SWITCH_EVENT_MESSAGE_WAITING, SWITCH_EVENT_SUBCLASS_ANY, mod_openzap_mwi_handler, NULL) != SWITCH_STATUS_SUCCESS) { + zap_log(ZAP_LOG_ERROR, "Error binding MWI to OpenZAP\n"); + } + SWITCH_ADD_API(commands_api_interface, "oz", "OpenZAP commands", oz_function, OZ_SYNTAX); SWITCH_ADD_APP(app_interface, "disable_ec", "Disable Echo Canceller", "Disable Echo Canceller", disable_ec_function, "", SAF_NONE); @@ -2988,6 +3155,8 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_openzap_shutdown) { + switch_event_unbind_callback(mod_openzap_mwi_handler); + zap_global_destroy(); // this breaks pika but they are MIA so *shrug* --- .src/mod/applications/mod_voicemail/.svn/text-base/mod_voicemail.c.svn-base 2010-02-11 11:00:12.000000000 +0100 +++ .src/mod/applications/mod_voicemail/mod_voicemail.c 2010-02-19 09:49:06.344058424 +0100 @@ -1653,7 +1661,7 @@ } -static void update_mwi(vm_profile_t *profile, const char *id, const char *domain_name, const char *myfolder) +static void update_mwi(vm_profile_t *profile, const char *id, const char *domain_name, const char *myfolder, const char *mwi_account) { const char *yn = "no"; int total_new_messages = 0; @@ -1673,13 +1681,16 @@ yn = "yes"; } switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "MWI-Messages-Waiting", yn); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "MWI-Message-Account", "%...@%s", id, domain_name); + if (mwi_account == NULL) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "MWI-Message-Account", "%...@%s", id, domain_name); + } else { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "MWI-Message-Account", "%s", mwi_account); + } switch_event_add_header(event, SWITCH_STACK_BOTTOM, "MWI-Voice-Message", "%d/%d (%d/%d)", total_new_messages, total_saved_messages, total_new_urgent_messages, total_saved_urgent_messages); switch_event_fire(&event); } - #define FREE_DOMAIN_ROOT() if (x_domain_root) switch_xml_free(x_domain_root); x_user = x_domain = x_domain_root = NULL @@ -1703,6 +1714,7 @@ int total_saved_urgent_messages = 0; int heard_auto_saved = 0, heard_auto_new = 0; char *vm_email = NULL, *email_addr = NULL; + char *mwi_account = NULL; char *convert_cmd = profile->convert_cmd; char *convert_ext = profile->convert_ext; char *vm_storage_dir = NULL; @@ -1872,7 +1884,7 @@ vm_execute_sql(profile, sql, profile->mutex); vm_check_state = VM_CHECK_FOLDER_SUMMARY; - update_mwi(profile, myid, domain_name, myfolder); + update_mwi(profile, myid, domain_name, myfolder, mwi_account); } break; case VM_CHECK_CONFIG: @@ -2145,6 +2157,8 @@ } else if (!strcasecmp(var, "timezone")) { switch_channel_set_variable(channel, var, val); + } else if (!strcasecmp(var, "MWI-Account")) { + mwi_account = switch_core_session_strdup(session, val); } } @@ -2279,6 +2293,7 @@ char *vm_notify_email = NULL; char *email_addr = NULL; char *vm_timezone = NULL; + char *mwi_account = NULL; int send_mail = 0; int send_main = 0; int send_notify = 0; @@ -2351,10 +2366,12 @@ convert_ext = switch_core_strdup(pool, val); } else if (!strcasecmp(var, "timezone")) { vm_timezone = switch_core_strdup(pool, val); + } else if (!strcasecmp(var, "MWI-Account")) { + mwi_account = switch_core_strdup(pool, val); } /*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send mail is %d, var is %s\n", send_mail, var); */ } - + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deliver VM to %...@%s\n", myid, domain_name); if (!zstr(vm_storage_dir)) { @@ -2415,7 +2432,7 @@ vm_execute_sql(profile, usql, profile->mutex); switch_safe_free(usql); - update_mwi(profile, myid, domain_name, myfolder); + update_mwi(profile, myid, domain_name, myfolder, mwi_account); } if (send_mail && !zstr(vm_email) && switch_file_exists(file_path, pool) == SWITCH_STATUS_SUCCESS) { @@ -3569,6 +3586,8 @@ char *sql; struct holder holder; char *ref = NULL; + char *mwi_account = NULL; + switch_xml_t x_domain = NULL, x_domain_root = NULL, x_user = NULL, x_params, x_param; if (stream->param_event) { ref = switch_event_get_header(stream->param_event, "http-referer"); @@ -3586,7 +3605,22 @@ vm_execute_sql(profile, sql, profile->mutex); free(sql); - update_mwi(profile, user, domain, myfolder); + if (switch_xml_locate_user("id", user, domain, NULL, &x_domain_root, &x_domain, &x_user, NULL, NULL) != SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "Can't find user [...@%s]\n", user, domain); + } else { + if ((x_params = switch_xml_child(x_user, "params"))) { + for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) { + const char *var = switch_xml_attr_soft(x_param, "name"); + const char *val = switch_xml_attr_soft(x_param, "value"); + + if (!strcasecmp(var, "MWI-Account")) { + mwi_account = switch_core_strdup(profile->pool, val); + } + } + } + } + + update_mwi(profile, user, domain, myfolder, mwi_account); if (ref) { stream->write_function(stream, "Content-type: text/html\n\n<h2>Message Deleted</h2>\n" "<META http-equiv=\"refresh\" content=\"1;URL=%s\">", ref);
_______________________________________________ FreeSWITCH-dev mailing list FreeSWITCH-dev@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev http://www.freeswitch.org