/** * Process <break>- this is a period of silence */ static int process_break(struct ssml_parser *parsed_data, char **atts) { if (atts) { int i = 0; while (atts[i]) { if (!strcmp("time", atts[i])) { char *t = atts[i + 1]; if (!zstr(t) && parsed_data->num_files < parsed_data->max_files) { int timeout_ms = 0; char *unit; if ((unit = strstr(t, "ms"))) { *unit = '\0'; if (switch_is_number(t)) { timeout_ms = atoi(t); } } else if ((unit = strstr(t, "s"))) { *unit = '\0'; if (switch_is_number(t)) { timeout_ms = atoi(t) * 1000; } } if (timeout_ms > 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding <break>: \"%s\"\n", t); parsed_data->files[parsed_data->num_files].name = switch_core_sprintf(parsed_data->pool, "silence_stream://%i", timeout_ms); parsed_data->files[parsed_data->num_files++].prefix = NULL; } } return IKS_OK; } i += 2; } } return IKS_OK; }
SWITCH_DECLARE(switch_log_level_t) switch_log_str2level(const char *str) { int x = 0; switch_log_level_t level = SWITCH_LOG_INVALID; if (switch_is_number(str)) { x = atoi(str); if (x > SWITCH_LOG_INVALID) { return SWITCH_LOG_INVALID - 1; } else if (x < 0) { return 0; } else { return x; } } for (x = 0;; x++) { if (!LEVELS[x]) { break; } if (!strcasecmp(LEVELS[x], str)) { level = (switch_log_level_t) x; break; } } return level; }
/*! set text parameter */ static void pocketsphinx_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val) { pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info; if (!zstr(param) && !zstr(val)) { if (!strcasecmp("no-input-timeout", param) && switch_is_number(val)) { ps->no_input_timeout = atoi(val); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "no-input-timeout = %d\n", ps->no_input_timeout); } else if (!strcasecmp("speech-timeout", param) && switch_is_number(val)) { ps->speech_timeout = atoi(val); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "speech-timeout = %d\n", ps->speech_timeout); } else if (!strcasecmp("start-input-timers", param)) { ps->start_input_timers = switch_true(val); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "start-input-timers = %d\n", ps->start_input_timers); } else if (!strcasecmp("confidence-threshold", param) && switch_is_number(val)) { ps->confidence_threshold = atoi(val); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "confidence-threshold = %d\n", ps->confidence_threshold); } } }
/** * Wraps file with interface that can be controlled by fileman flags * @param handle * @param path the file to play * @return SWITCH_STATUS_SUCCESS if opened */ static switch_status_t fileman_file_open(switch_file_handle_t *handle, const char *path) { int start_offset_ms = 0; switch_status_t status = SWITCH_STATUS_FALSE; struct fileman_file_context *context = switch_core_alloc(handle->memory_pool, sizeof(*context)); handle->private_info = context; if (handle->params) { const char *id = switch_event_get_header(handle->params, "id"); const char *uuid = switch_event_get_header(handle->params, "session"); const char *start_offset_ms_str = switch_event_get_header(handle->params, "start_offset_ms"); if (!zstr(id)) { context->id = switch_core_strdup(handle->memory_pool, id); } if (!zstr(uuid)) { context->uuid = switch_core_strdup(handle->memory_pool, uuid); } if (!zstr(start_offset_ms_str) && switch_is_number(start_offset_ms_str)) { start_offset_ms = atoi(start_offset_ms_str); if (start_offset_ms < 0) { start_offset_ms = 0; } } } switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Got path %s\n", path); if ((status = switch_core_file_open(&context->fh, path, handle->channels, handle->samplerate, handle->flags, NULL)) != SWITCH_STATUS_SUCCESS) { return status; } /* set up handle for external control */ if (!context->id) { /* use filename as ID */ context->id = switch_core_strdup(handle->memory_pool, path); } switch_mutex_lock(fileman_globals.mutex); if (!switch_core_hash_find(fileman_globals.hash, context->id)) { switch_core_hash_insert(fileman_globals.hash, context->id, handle); } else { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_WARNING, "Duplicate fileman ID: %s\n", context->id); return SWITCH_STATUS_FALSE; } switch_mutex_unlock(fileman_globals.mutex); context->max_frame_len = (handle->samplerate / 1000 * SWITCH_MAX_INTERVAL); switch_zmalloc(context->abuf, FILE_STARTBYTES * sizeof(*context->abuf)); if (!context->fh.audio_buffer) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Create audio buffer\n"); switch_buffer_create_dynamic(&context->fh.audio_buffer, FILE_BLOCKSIZE, FILE_BUFSIZE, 0); switch_assert(context->fh.audio_buffer); } handle->samples = context->fh.samples; handle->format = context->fh.format; handle->sections = context->fh.sections; handle->seekable = context->fh.seekable; handle->speed = context->fh.speed; handle->vol = context->fh.vol; handle->offset_pos = context->fh.offset_pos; handle->interval = context->fh.interval; if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) { switch_set_flag(handle, SWITCH_FILE_NATIVE); } else { switch_clear_flag(handle, SWITCH_FILE_NATIVE); } if (handle->params && switch_true(switch_event_get_header(handle->params, "pause"))) { switch_set_flag(handle, SWITCH_FILE_PAUSE); } if (handle->seekable && start_offset_ms) { unsigned int pos = 0; int32_t target = start_offset_ms * (handle->samplerate / 1000); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", target); switch_core_file_seek(&context->fh, &pos, target, SEEK_SET); } return status; }
/** * Handle fax completion event from FreeSWITCH core * @param event received from FreeSWITCH core. It will be destroyed by the core after this function returns. */ static void on_execute_complete_event(switch_event_t *event) { const char *application = switch_event_get_header(event, "Application"); if (!zstr(application) && (!strcmp(application, "rxfax") || !strcmp(application, "txfax"))) { int is_rxfax = !strcmp(application, "rxfax"); const char *uuid = switch_event_get_header(event, "Unique-ID"); const char *fax_jid = switch_event_get_header(event, "variable_rayo_fax_jid"); struct rayo_actor *component; if (!zstr(fax_jid) && (component = RAYO_LOCATE(fax_jid))) { iks *result; iks *complete; iks *fax; int have_fax_document = 1; switch_core_session_t *session; switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Got result for %s\n", fax_jid); /* clean up channel */ session = switch_core_session_locate(uuid); if (session) { switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL); switch_core_session_rwunlock(session); } /* RX only: transfer HTTP document and delete local copy */ if (is_rxfax && RECEIVEFAX_COMPONENT(component)->http_put_after_receive && switch_file_exists(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component)) == SWITCH_STATUS_SUCCESS) { switch_stream_handle_t stream = { 0 }; SWITCH_STANDARD_STREAM(stream); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s PUT fax to %s\n", RAYO_JID(component), RECEIVEFAX_COMPONENT(component)->filename); switch_api_execute("http_put", RECEIVEFAX_COMPONENT(component)->filename, NULL, &stream); /* check if successful */ if (!zstr(stream.data) && strncmp(stream.data, "+OK", 3)) { /* PUT failed */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s PUT fax to %s failed: %s\n", RAYO_JID(component), RECEIVEFAX_COMPONENT(component)->filename, (char *)stream.data); have_fax_document = 0; } switch_safe_free(stream.data) switch_file_remove(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component)); } /* successful fax? */ if (have_fax_document && switch_true(switch_event_get_header(event, "variable_fax_success"))) { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), FAX_FINISH); } else if (have_fax_document && FAX_COMPONENT(component)->stop) { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_STOP); } else { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_ERROR); } complete = iks_find(result, "complete"); /* RX only: add fax document information */ if (is_rxfax && have_fax_document) { const char *pages = switch_event_get_header(event, "variable_fax_document_transferred_pages"); if (!zstr(pages) && switch_is_number(pages) && atoi(pages) > 0) { const char *resolution = switch_event_get_header(event, "variable_fax_file_image_resolution"); const char *size = switch_event_get_header(event, "variable_fax_image_size"); fax = iks_insert(complete, "fax"); iks_insert_attrib(fax, "xmlns", RAYO_FAX_COMPLETE_NS); if (RECEIVEFAX_COMPONENT(component)->http_put_after_receive) { iks_insert_attrib(fax, "url", RECEIVEFAX_COMPONENT(component)->filename); } else { /* convert absolute path to file:// URI */ iks_insert_attrib_printf(fax, "url", "file://%s", RECEIVEFAX_COMPONENT(component)->filename); } if (!zstr(resolution)) { iks_insert_attrib(fax, "resolution", resolution); } if (!zstr(size)) { iks_insert_attrib(fax, "size", size); } iks_insert_attrib(fax, "pages", pages); } } /* add metadata from event */ insert_fax_metadata(event, "fax_success", complete); insert_fax_metadata(event, "fax_result_code", complete); insert_fax_metadata(event, "fax_result_text", complete); insert_fax_metadata(event, "fax_document_transferred_pages", complete); insert_fax_metadata(event, "fax_document_total_pages", complete); insert_fax_metadata(event, "fax_image_resolution", complete); insert_fax_metadata(event, "fax_image_size", complete); insert_fax_metadata(event, "fax_bad_rows", complete); insert_fax_metadata(event, "fax_transfer_rate", complete); insert_fax_metadata(event, "fax_ecm_used", complete); insert_fax_metadata(event, "fax_local_station_id", complete); insert_fax_metadata(event, "fax_remote_station_id", complete); /* flag faxing as done */ rayo_call_set_faxing(RAYO_CALL(RAYO_COMPONENT(component)->parent), 0); rayo_component_send_complete_event(RAYO_COMPONENT(component), result); RAYO_UNLOCK(component); } } }
/** * read default settings from speex.conf */ static void load_configuration() { switch_xml_t xml = NULL, cfg = NULL; if ((xml = switch_xml_open_cfg("speex.conf", &cfg, NULL))) { switch_xml_t x_lists; if ((x_lists = switch_xml_child(cfg, "settings"))) { const char *settings_name = switch_xml_attr(x_lists, "name"); switch_xml_t x_list; if (zstr(settings_name)) { settings_name = ""; } for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) { const char *name = switch_xml_attr(x_list, "name"); const char *value = switch_xml_attr(x_list, "value"); if (zstr(name)) { continue; } if (zstr(value)) { continue; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s %s = %s\n", settings_name, name, value); if (!strcasecmp("quality", name)) { /* compression quality, integer 0-10 */ int tmp = atoi(value); if (switch_is_number(value) && tmp >= 0 && tmp <= 10) { default_codec_settings.quality = tmp; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid quality value: %s\n", value); } } else if (!strcasecmp("complexity", name)) { /* compression complexity, integer 1-10 */ int tmp = atoi(value); if (switch_is_number(value) && tmp >= 1 && tmp <= 10) { default_codec_settings.complexity = tmp; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid complexity value: %s\n", value); } } else if (!strcasecmp("enhancement", name)) { /* enable perceptual enhancement, boolean */ default_codec_settings.enhancement = switch_true(value); } else if (!strcasecmp("vad", name)) { /* enable voice activity detection, boolean */ default_codec_settings.vad = switch_true(value); } else if (!strcasecmp("vbr", name)) { /* enable variable bit rate, boolean */ default_codec_settings.vbr = switch_true(value); } else if (!strcasecmp("vbr-quality", name)) { /* variable bit rate quality, float 0-10 */ float tmp = atof(value); if (switch_is_number(value) && tmp >= 0 && tmp <= 10) { default_codec_settings.vbr_quality = tmp; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid vbr-quality value: %s\n", value); } } else if (!strcasecmp("abr", name)) { /* average bit rate, integer bits per sec */ int tmp = atoi(value); if (switch_is_number(value) && tmp >= 0) { default_codec_settings.abr = tmp; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid abr value: %s\n", value); } } else if (!strcasecmp("dtx", name)) { /* discontinuous transmit, boolean */ default_codec_settings.dtx = switch_true(value); } else if (!strcasecmp("preproc", name)) { /* enable preprocessor, boolean */ default_codec_settings.preproc = switch_true(value); } else if (!strcasecmp("pp-vad", name)) { /* enable preprocessor VAD, boolean */ default_codec_settings.pp_vad = switch_true(value); } else if (!strcasecmp("pp-agc", name)) { /* enable preprocessor automatic gain control, boolean */ default_codec_settings.pp_agc = switch_true(value); } else if (!strcasecmp("pp-agc-level", name)) { /* agc level, float */ float tmp = atof(value); if (switch_is_number(value) && tmp >= 0.0f) { default_codec_settings.pp_agc_level = tmp; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid pp-agc-level value: %s\n", value); } } else if (!strcasecmp("pp-denoise", name)) { /* enable preprocessor denoiser, boolean */ default_codec_settings.pp_denoise = switch_true(value); } else if (!strcasecmp("pp-dereverb", name)) { /* enable preprocessor reverberation removal, boolean */ default_codec_settings.pp_dereverb = switch_true(value); } else if (!strcasecmp("pp-dereverb-decay", name)) { /* reverberation removal decay, float */ float tmp = atof(value); if (switch_is_number(value) && tmp >= 0.0f) { default_codec_settings.pp_dereverb_decay = tmp; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid pp-dereverb-decay value: %s\n", value); } } else if (!strcasecmp("pp-dereverb-level", name)) { /* reverberation removal level, float */ float tmp = atof(value); if (switch_is_number(value) && tmp >= 0.0f) { default_codec_settings.pp_dereverb_level = tmp; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid pp-dereverb-level value: %s\n", value); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid unknown param: %s = %s\n", name, value); } } } switch_xml_free(xml); } }
static switch_status_t switch_speex_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp) { speex_codec_settings_t *codec_settings = NULL; int x, argc; char *argv[10]; char *fmtp_dup = NULL; if (!codec_fmtp) { return SWITCH_STATUS_FALSE; } /* load default settings */ if (codec_fmtp->private_info) { codec_settings = codec_fmtp->private_info; memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings)); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "codec_fmtp->private_info is NULL\n"); return SWITCH_STATUS_SUCCESS; } if (!fmtp) { return SWITCH_STATUS_SUCCESS; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "got fmtp: %s\n", fmtp); fmtp_dup = strdup(fmtp); switch_assert(fmtp_dup); /* parse ; separated fmtp args */ argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0]))); for (x = 0; x < argc; x++) { char *data = argv[x]; char *arg; switch_assert(data); while (*data == ' ') { data++; } if (!(arg = strchr(data, '='))) { continue; } *arg++ = '\0'; if (zstr(arg)) { continue; } if (!strcasecmp("vbr", data)) { /* vbr can be on/off/vad */ if (!strcasecmp("vad", arg)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "enabling speex vbr=vad\n"); codec_settings->vbr = 0; codec_settings->vad = 1; codec_settings->pp_vad = 1; } else { if (switch_true(arg)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "enabling speex vbr\n"); codec_settings->vbr = 1; codec_settings->vad = 0; codec_settings->pp_vad = 1; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "disabling speex vbr\n"); codec_settings->vbr = 0; codec_settings->vad = 0; codec_settings->pp_vad = 0; } } } else if (!strcasecmp("cng", data)) { /* TODO don't know how to turn on CNG */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "speex cng is unsupported\n"); } else if (!strcasecmp("mode", data)) { /* mode is a comma-separate list of preferred modes. Use the first mode in the list */ char *arg_dup; char *mode[2]; if (!strncasecmp("any", arg, 3)) { /* "any", keep the default setting */ continue; } arg_dup = strdup(arg); if (switch_separate_string(arg_dup, ',', mode, (sizeof(mode) / sizeof(mode[0])))) { int mode_num = -1; char *mode_str = mode[0]; if (mode_str[0] == '"') { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "mode starts with \"\n"); mode_str++; } if (switch_is_number(mode_str)) { mode_num = atoi(mode_str); } /* TODO there might be a way to set the mode directly instead of changing the quality */ if (codec_fmtp->actual_samples_per_second == 8000) { switch (mode_num) { case 1: codec_settings->quality = 0; break; case 2: codec_settings->quality = 2; break; case 3: codec_settings->quality = 4; break; case 4: codec_settings->quality = 6; break; case 5: codec_settings->quality = 8; break; case 6: codec_settings->quality = 9; break; case 7: codec_settings->quality = 10; break; case 8: codec_settings->quality = 1; break; default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "ignoring invalid speex/8000 mode %s\n", mode_str); continue; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "choosing speex/8000 mode %s\n", mode_str); codec_settings->quality = codec_settings->quality; codec_settings->vbr_quality = codec_settings->quality; } else { if (mode_num >= 0 && mode_num <= 10) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "choosing speex/%d mode %s\n", codec_fmtp->actual_samples_per_second, mode_str); codec_settings->quality = mode_num; codec_settings->vbr_quality = mode_num; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "ignoring invalid speex/%d mode %s\n", codec_fmtp->actual_samples_per_second, mode_str); continue; } } } free(arg_dup); } } free(fmtp_dup); /*codec_fmtp->bits_per_second = bit_rate;*/ return SWITCH_STATUS_SUCCESS; }
switch_status_t ladspa_session(switch_core_session_t *session, const char *flags, const char *plugin_name, const char *label, const char *params) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_media_bug_t *bug; switch_status_t status; switch_ladspa_t *pvt = { 0 }; switch_codec_implementation_t read_impl = { 0 }; int i, bflags = SMBF_READ_REPLACE | SMBF_ANSWER_REQ; char *pstr; int argc; char *argv[50]; char *dparams = NULL; if (zstr(plugin_name)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s INVALID PLUGIN\n", switch_channel_get_name(channel)); return SWITCH_STATUS_FALSE; } if (zstr(flags)) { flags = "r"; } if (strchr(flags, 'w')) { bflags = SMBF_WRITE_REPLACE; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "FLAGS: %s PLUGIN: %s LABEL: %s PARAMS: %s\n", flags, plugin_name, label, params); switch_core_session_get_read_impl(session, &read_impl); pvt = switch_core_session_alloc(session, sizeof(*pvt)); pvt->session = session; if (!zstr(label)) { pvt->label_name = switch_core_session_strdup(session, label); } else { char *p; pvt->label_name = switch_core_session_strdup(session, plugin_name); if ((p = strrchr(pvt->label_name, '.'))) { *p = '\0'; } } if (strstr(plugin_name, ".so")) { pvt->plugin_name = switch_core_session_strdup(session, plugin_name); } else { pvt->plugin_name = switch_core_session_sprintf(session, "%s.so", plugin_name); } dparams = switch_core_session_strdup(session, params); argc = switch_split(dparams, ' ', argv); for (i = 0; i < argc; i++) { if (switch_is_number(argv[i])) { if (pvt->num_idx < MAX_INDEX) { pvt->config[pvt->num_idx] = atof(argv[i]); pvt->has_config[pvt->num_idx] = 1; pvt->num_idx++; } } else { if (pvt->str_idx < MAX_INDEX) { pvt->str_config[pvt->str_idx++] = switch_core_session_strdup(session, argv[i]); } } } if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_FALSE; } pstr = switch_core_session_sprintf(session, "%s|%s|%s|%s", flags, plugin_name, label, params); if ((status = switch_core_media_bug_add(session, "ladspa", pstr, ladspa_callback, pvt, 0, bflags | SMBF_NO_PAUSE, &bug)) != SWITCH_STATUS_SUCCESS) { return status; } switch_channel_set_private(channel, "ladspa", bug); return SWITCH_STATUS_SUCCESS; }
switch_status_t spandsp_inband_dtmf_session(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_media_bug_t *bug; switch_status_t status; switch_inband_dtmf_t *pvt; switch_codec_implementation_t read_impl = { 0 }; const char *value; switch_core_session_get_read_impl(session, &read_impl); if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) { return SWITCH_STATUS_MEMERR; } pvt->session = session; /* get detector params */ pvt->min_dup_digit_spacing = 0; value = switch_channel_get_variable(channel, "min_dup_digit_spacing_ms"); if (!zstr(value) && switch_is_number(value)) { int val = atoi(value) * 8; /* convert from ms to samples */ if (val < 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "min_dup_digit_spacing_ms must be >= 0\n"); } else { pvt->min_dup_digit_spacing = val; } } pvt->threshold = -100; value = switch_channel_get_variable(channel, "spandsp_dtmf_rx_threshold"); if (!zstr(value) && switch_is_number(value)) { int val = atoi(value); if (val < -99) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "spandsp_dtmf_rx_threshold must be >= -99 dBm0\n"); } else { pvt->threshold = val; } } pvt->twist = -1; value = switch_channel_get_variable(channel, "spandsp_dtmf_rx_twist"); if (!zstr(value) && switch_is_number(value)) { int val = atoi(value); if (val < 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "spandsp_dtmf_rx_twist must be >= 0 dB\n"); } else { pvt->twist = val; } } pvt->reverse_twist = -1; value = switch_channel_get_variable(channel, "spandsp_dtmf_rx_reverse_twist"); if (!zstr(value) && switch_is_number(value)) { int val = atoi(value); if (val < 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "spandsp_dtmf_rx_reverse_twist must be >= 0 dB\n"); } else { pvt->reverse_twist = val; } } pvt->filter_dialtone = -1; value = switch_channel_get_variable(channel, "spandsp_dtmf_rx_filter_dialtone"); if (switch_true(value)) { pvt->filter_dialtone = 1; } else if (switch_false(value)) { pvt->filter_dialtone = 0; } if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_FALSE; } if ((status = switch_core_media_bug_add(session, "spandsp_dtmf_detect", NULL, inband_dtmf_callback, pvt, 0, SMBF_READ_REPLACE | SMBF_NO_PAUSE, &bug)) != SWITCH_STATUS_SUCCESS) { return status; } switch_channel_set_private(channel, "dtmf", bug); return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_xml_config_parse_event(switch_event_t *event, int count, switch_bool_t reload, switch_xml_config_item_t *instructions) { switch_xml_config_item_t *item; int matched_count = 0; for (item = instructions; item->key; item++) { const char *value = switch_event_get_header(event, item->key); switch_bool_t changed = SWITCH_FALSE; switch_xml_config_callback_t callback = (switch_xml_config_callback_t) item->function; void *ptr = item->ptr; //switch_assert(ptr); if (value) { matched_count++; } if (reload && !switch_test_flag(item, CONFIG_RELOADABLE)) { continue; } if (!value && switch_test_flag(item, CONFIG_REQUIRED)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Required parameter [%s] is missing\n", item->key); return SWITCH_STATUS_FALSE; } switch (item->type) { case SWITCH_CONFIG_INT: { switch_xml_config_int_options_t *int_options = (switch_xml_config_int_options_t *) item->data; int *dest = (int *) ptr; int intval; if (value) { if (switch_is_number(value)) { intval = atoi(value); } else { intval = (int) (intptr_t) item->defaultvalue; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], setting default [%d]\n", value, item->key, intval); } if (int_options) { /* Enforce validation options */ if ((int_options->enforce_min && !(intval >= int_options->min)) || (int_options->enforce_max && !(intval <= int_options->max))) { /* Validation failed, set default */ intval = (int) (intptr_t) item->defaultvalue; /* Then complain */ if (int_options->enforce_min && int_options->enforce_max) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], should be between [%d] and [%d], setting default [%d]\n", value, item->key, int_options->min, int_options->max, intval); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], should be %s [%d], setting default [%d]\n", value, item->key, int_options->enforce_min ? "at least" : "at max", int_options->enforce_min ? int_options->min : int_options->max, intval); } } } } else { intval = (int) (intptr_t) item->defaultvalue; } if (*dest != intval) { *dest = intval; changed = SWITCH_TRUE; } } break; case SWITCH_CONFIG_ATOMIC: { switch_xml_config_atomic_options_t *atomic_options = (switch_xml_config_atomic_options_t *) item->data; switch_atomic_t *dest = (switch_atomic_t *) ptr; uint32_t uintval; if (value) { if (switch_is_number(value)) { uintval = (uint32_t) strtol(value, NULL, 10); } else { uintval = (uint32_t) (uintptr_t) item->defaultvalue; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], setting default [%u]\n", value, item->key, uintval); } if (atomic_options) { /* Enforce validation options */ if ((atomic_options->enforce_min && !(uintval >= atomic_options->min)) || (atomic_options->enforce_max && !(uintval <= atomic_options->max))) { /* Validation failed, set default */ uintval = (uint32_t) (uintptr_t) item->defaultvalue; /* Then complain */ if (atomic_options->enforce_min && atomic_options->enforce_max) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], should be between [%u] and [%u], setting default [%u]\n", value, item->key, atomic_options->min, atomic_options->max, uintval); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], should be %s [%u], setting default [%u]\n", value, item->key, atomic_options->enforce_min ? "at least" : "at max", atomic_options->enforce_min ? atomic_options->min : atomic_options->max, uintval); } } } } else { uintval = (uint32_t) (uintptr_t) item->defaultvalue; } if (switch_atomic_read(dest) != uintval) { switch_atomic_set(dest, uintval); changed = SWITCH_TRUE; } } break; case SWITCH_CONFIG_STRING: { switch_xml_config_string_options_t string_options_default = { 0 }; switch_xml_config_string_options_t *string_options = item->data ? (switch_xml_config_string_options_t *) item->data : &string_options_default; const char *newstring = NULL; /* Perform validation */ if (value) { if (!zstr(string_options->validation_regex)) { if (switch_regex_match(value, string_options->validation_regex) == SWITCH_STATUS_SUCCESS) { newstring = value; /* Regex match, accept value */ } else { newstring = (char *) item->defaultvalue; /* Regex failed */ if (newstring) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], setting default [%s]\n", value, item->key, newstring); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s]\n", value, item->key); } switch_xml_config_item_print_doc(SWITCH_LOG_ERROR, item); } } else { newstring = value; /* No validation */ } } else { newstring = (char *) item->defaultvalue; } if (string_options->length > 0) { /* We have a preallocated buffer */ char *dest = (char *) ptr; if (newstring) { if (strncasecmp(dest, newstring, string_options->length)) { switch_copy_string(dest, newstring, string_options->length); changed = SWITCH_TRUE; } } else { if (*dest != '\0') { *dest = '\0'; changed = SWITCH_TRUE; } } } else if (string_options->pool) { /* Pool-allocated buffer */ char **dest = (char **) ptr; if (newstring) { if (!*dest || strcmp(*dest, newstring)) { *dest = switch_core_strdup(string_options->pool, newstring); } } else { if (*dest) { changed = SWITCH_TRUE; *dest = NULL; } } } else { /* Dynamically allocated buffer */ char **dest = (char **) ptr; if (newstring) { if (!*dest || strcmp(*dest, newstring)) { switch_safe_free(*dest); *dest = strdup(newstring); changed = SWITCH_TRUE; } } else { if (*dest) { switch_safe_free(*dest); changed = SWITCH_TRUE; } } } } break; case SWITCH_CONFIG_BOOL: { switch_bool_t *dest = (switch_bool_t *) ptr; switch_bool_t newval = SWITCH_FALSE; if (value && switch_true(value)) { newval = SWITCH_TRUE; } else if (value && switch_false(value)) { newval = SWITCH_FALSE; } else if (value) { /* Value isnt true or false */ newval = (switch_bool_t) (intptr_t) item->defaultvalue; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], setting default [%s]\n", value, item->key, newval ? "true" : "false"); switch_xml_config_item_print_doc(SWITCH_LOG_ERROR, item); } else { newval = (switch_bool_t) (intptr_t) item->defaultvalue; } if (*dest != newval) { *dest = newval; changed = SWITCH_TRUE; } } break; case SWITCH_CONFIG_CUSTOM: break; case SWITCH_CONFIG_ENUM: { switch_xml_config_enum_item_t *enum_options = (switch_xml_config_enum_item_t *) item->data; int *dest = (int *) ptr; int newval = 0; switch_status_t lookup_result = SWITCH_STATUS_SUCCESS; if (value) { lookup_result = switch_xml_config_enum_str2int(enum_options, value, &newval); } else { newval = (int) (intptr_t) item->defaultvalue; } if (lookup_result != SWITCH_STATUS_SUCCESS) { newval = (int) (intptr_t) item->defaultvalue; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s]\n", value, item->key); switch_xml_config_item_print_doc(SWITCH_LOG_ERROR, item); } if (*dest != newval) { changed = SWITCH_TRUE; *dest = newval; } } break; case SWITCH_CONFIG_FLAG: { int32_t *dest = (int32_t *) ptr; int index = (int) (intptr_t) item->data; int8_t currentval = (int8_t) ! !(*dest & index); int newval = 0; if (value) { newval = switch_true(value); } else { newval = (switch_bool_t) (intptr_t) item->defaultvalue; } if (newval != currentval) { changed = SWITCH_TRUE; if (newval) { *dest |= (1 << index); } else { *dest &= ~(1 << index); } } } break; case SWITCH_CONFIG_FLAGARRAY: { int8_t *dest = (int8_t *) ptr; unsigned int index = (unsigned int) (intptr_t) item->data; int8_t newval = value ? !!switch_true(value) : (int8_t) ((intptr_t) item->defaultvalue); if (dest[index] != newval) { changed = SWITCH_TRUE; dest[index] = newval; } } break; case SWITCH_CONFIG_LAST: break; default: break; } if (callback) { callback(item, value, (reload ? CONFIG_RELOAD : CONFIG_LOAD), changed); } } if (count != matched_count) { /* User made a mistake, find it */ switch_event_header_t *header; for (header = event->headers; header; header = header->next) { switch_bool_t found = SWITCH_FALSE; for (item = instructions; item->key; item++) { if (!strcasecmp(header->name, item->key)) { found = SWITCH_TRUE; break; } } if (!found) { /* Tell the user */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Configuration parameter [%s] is unfortunately not valid, you might want to double-check that.\n", header->name); } } } return SWITCH_STATUS_SUCCESS; }
/** * Configure module */ static switch_status_t do_config(void) { switch_xml_t cfg, xml, settings; if (!(xml = switch_xml_open_cfg("graylog2.conf", &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of graylog2.conf failed\n"); return SWITCH_STATUS_TERM; } /* set defaults */ globals.log_level = SWITCH_LOG_WARNING; globals.server_host = "127.0.0.1"; globals.server_port = 12201; globals.send_uncompressed_header = 0; if ((settings = switch_xml_child(cfg, "settings"))) { switch_xml_t param; switch_xml_t fields; for (param = switch_xml_child(settings, "param"); param; param = param->next) { char *name = (char *) switch_xml_attr_soft(param, "name"); char *value = (char *) switch_xml_attr_soft(param, "value"); if (zstr(name)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring empty param\n"); continue; } if (zstr(value)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring empty value for param \"%s\"\n", name); continue; } if (!strcmp(name, "server-host")) { globals.server_host = switch_core_strdup(globals.pool, value); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\"%s\" = \"%s\"\n", name, value); } else if (!strcasecmp(name, "server-port")) { int port = -1; if (switch_is_number(value)) { port = atoi(value); } if (port > 0 && port <= 65535) { globals.server_port = port; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\"%s\" = \"%s\"\n", name, value); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid port: \"%s\"\n", value); } } else if (!strcasecmp(name, "loglevel")) { switch_log_level_t log_level = switch_log_str2level(value); if (log_level == SWITCH_LOG_INVALID) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring invalid log level: \"%s\"\n", value); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\"%s\" = \"%s\"\n", name, value); globals.log_level = log_level; } } else if (!strcasecmp(name, "send-uncompressed-header")) { globals.send_uncompressed_header = switch_true(value); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\"%s\" = \"%s\"\n", name, value); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring unknown param: \"%s\"\n", name); } } /* map session fields to channel variables */ if ((fields = switch_xml_child(settings, "fields"))) { switch_xml_t field; for (field = switch_xml_child(fields, "field"); field; field = field->next) { char *name = (char *) switch_xml_attr_soft(field, "name"); char *variable = (char *) switch_xml_attr_soft(field, "variable"); if (zstr(name)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring unnamed session field\n"); continue; } if (zstr(variable)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring empty channel variable for session field \"%s\"\n", name); continue; } switch_event_add_header_string(globals.session_fields, SWITCH_STACK_BOTTOM, switch_core_strdup(globals.pool, name), switch_core_strdup(globals.pool, variable)); } } } switch_xml_free(xml); return SWITCH_STATUS_SUCCESS; }