static int container_test3_helper(int nolocking, struct ast_test *test) { int x; int res = AST_TEST_PASS; struct ast_format_cap *cap1; struct ast_format_cap *cap2; struct ast_format_cap *joint; for (x = 0; x < 2000; x++) { if (nolocking) { cap1 = ast_format_cap_alloc_nolock(); cap2 = ast_format_cap_alloc_nolock(); joint = ast_format_cap_alloc_nolock(); } else { cap1 = ast_format_cap_alloc(); cap2 = ast_format_cap_alloc(); joint = ast_format_cap_alloc(); } if (!cap1 || !cap2 || !joint) { ast_test_status_update(test, "cap alloc fail\n"); return AST_TEST_FAIL; } ast_format_cap_add_all(cap1); ast_format_cap_add_all_by_type(cap2, AST_FORMAT_TYPE_AUDIO); ast_format_cap_joint_copy(cap1, cap2, joint); if (!(ast_format_cap_identical(cap2, joint))) { ast_test_status_update(test, "failed identical test\n"); res = AST_TEST_FAIL; cap1 = ast_format_cap_destroy(cap1); cap2 = ast_format_cap_destroy(cap2); joint = ast_format_cap_destroy(joint); break; } cap1 = ast_format_cap_destroy(cap1); cap2 = ast_format_cap_destroy(cap2); joint = ast_format_cap_destroy(joint); } return res; }
struct ast_format_cap *ast_format_cap_dup(const struct ast_format_cap *cap) { struct ast_format_cap *dst; if (cap->nolock) { dst = ast_format_cap_alloc_nolock(); } else { dst = ast_format_cap_alloc(); } if (!dst) { return NULL; } ao2_callback(cap->formats, OBJ_NODATA | cap->nolock, copy_cb, dst); return dst; }
/** \brief Load module */ static int load_module(void) { ast_log(LOG_NOTICE, "Load Res-Speech-UniMRCP module\n"); if(uni_engine_load() == FALSE) { return AST_MODULE_LOAD_FAILURE; } if(mrcp_client_start(uni_engine.client) != TRUE) { ast_log(LOG_ERROR, "Failed to start MRCP client\n"); uni_engine_unload(); return AST_MODULE_LOAD_FAILURE; } #if AST_VERSION_AT_LEAST(10,0,0) #if AST_VERSION_AT_LEAST(13,0,0) ast_engine.formats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); #elif AST_VERSION_AT_LEAST(12,0,0) ast_engine.formats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); #else /* <= 11 */ ast_engine.formats = ast_format_cap_alloc_nolock(); #endif if(!ast_engine.formats) { ast_log(LOG_ERROR, "Failed to alloc media format capabilities\n"); uni_engine_unload(); return AST_MODULE_LOAD_FAILURE; } #if AST_VERSION_AT_LEAST(13,0,0) ast_format_cap_append(ast_engine.formats, ast_format_slin, 0); #else struct ast_format format; ast_format_set(&format, AST_FORMAT_SLINEAR, 0); ast_format_cap_add(ast_engine.formats, &format); #endif #else /* <= 1.8 */ ast_engine.formats = AST_FORMAT_SLINEAR; #endif if(ast_speech_register(&ast_engine)) { ast_log(LOG_ERROR, "Failed to register module\n"); mrcp_client_shutdown(uni_engine.client); uni_engine_unload(); return AST_MODULE_LOAD_FAILURE; } return AST_MODULE_LOAD_SUCCESS; }
static int parkandannounce_exec(struct ast_channel *chan, const char *data) { int res = -1; int lot, timeout = 0, dres; char *dialtech, *tmp[100], buf[13]; int looptemp, i; char *s; struct ast_channel *dchan; struct outgoing_helper oh = { 0, }; int outstate; struct ast_format tmpfmt; struct ast_format_cap *cap_slin = ast_format_cap_alloc_nolock(); AST_DECLARE_APP_ARGS(args, AST_APP_ARG(template);
static int nv_detectfax_exec(struct ast_channel *chan, const char *data) { int res = 0; char tmp[256] = "\0"; char *p = NULL; char *waitstr = NULL; char *options = NULL; char *silstr = NULL; char *minstr = NULL; char *maxstr = NULL; struct ast_frame *fr = NULL; struct ast_frame *fr2 = NULL; int notsilent = 0; struct timeval start = {0, 0}, end = {0, 0}; int waitdur = 4; int sildur = 1000; int mindur = 100; int maxdur = -1; int skipanswer = 0; int noextneeded = 0; int ignoredtmf = 0; int ignorefax = 0; int ignoretalk = 0; int x = 0; struct ast_format* origrformat = NULL; int features = 0; time_t timeout = 0; struct ast_dsp *dsp = NULL; struct ast_format_cap *cap; struct ast_format linearFormat; /* linear format capabilities */ ast_format_set(&linearFormat, AST_FORMAT_SLINEAR, 0); cap = ast_format_cap_alloc_nolock(); ast_format_cap_add(cap, &linearFormat); /* done */ pbx_builtin_setvar_helper(chan, "FAX_DETECTED", ""); pbx_builtin_setvar_helper(chan, "FAXEXTEN", ""); pbx_builtin_setvar_helper(chan, "DTMF_DETECTED", ""); pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ""); if (data || !ast_strlen_zero(data)) { strncpy(tmp, data, sizeof(tmp)-1); } p = tmp; waitstr = strsep(&p, ","); options = strsep(&p, ","); silstr = strsep(&p, ","); minstr = strsep(&p, ","); maxstr = strsep(&p, ","); if (waitstr) { if ((sscanf(waitstr, "%d", &x) == 1) && (x > 0)) waitdur = x; } if (options) { if (strchr(options, 'n')) skipanswer = 1; if (strchr(options, 'x')) noextneeded = 1; if (strchr(options, 'd')) ignoredtmf = 1; if (strchr(options, 'f')) ignorefax = 1; if (strchr(options, 't')) ignoretalk = 1; } if (silstr) { if ((sscanf(silstr, "%d", &x) == 1) && (x > 0)) sildur = x; } if (minstr) { if ((sscanf(minstr, "%d", &x) == 1) && (x > 0)) mindur = x; } if (maxstr) { if ((sscanf(maxstr, "%d", &x) == 1) && (x > 0)) maxdur = x; } ast_log(LOG_DEBUG, "Preparing detect of fax (waitdur=%dms, sildur=%dms, mindur=%dms, maxdur=%dms)\n", waitdur, sildur, mindur, maxdur); // LOCAL_USER_ADD(u); // if (chan->_state != AST_STATE_UP && !skipanswer) { if (ast_channel_state(chan) != AST_STATE_UP && !skipanswer) { /* Otherwise answer unless we're supposed to send this while on-hook */ res = ast_answer(chan); } if (!res) { // origrformat = chan->readformat; origrformat = ast_channel_readformat(chan); // if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR))) if ((res = ast_set_read_format_from_cap(chan, cap)) ){ ast_log(LOG_WARNING, "Unable to set read format to linear!\n"); } } if (!(dsp = ast_dsp_new())) { ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); res = -1; } if (dsp) { if (!ignoretalk) ; /* features |= DSP_FEATURE_SILENCE_SUPPRESS; */ if (!ignorefax) features |= DSP_FEATURE_FAX_DETECT; //if (!ignoredtmf) features |= DSP_FEATURE_DIGIT_DETECT; ast_dsp_set_threshold(dsp, 256); ast_dsp_set_features(dsp, features | DSP_DIGITMODE_RELAXDTMF); ast_dsp_set_digitmode(dsp, DSP_DIGITMODE_DTMF); } if (!res) { if (waitdur > 0) timeout = time(NULL) + (time_t)waitdur; while(ast_waitfor(chan, -1) > -1) { if (waitdur > 0 && time(NULL) > timeout) { res = 0; break; } fr = ast_read(chan); if (!fr) { ast_log(LOG_DEBUG, "Got hangup\n"); res = -1; break; } fr2 = ast_dsp_process(chan, dsp, fr); if (!fr2) { ast_log(LOG_WARNING, "Bad DSP received (what happened?)\n"); fr2 = fr; } if (fr2->frametype == AST_FRAME_DTMF) { if (fr2->subclass.integer == 'f' && !ignorefax) { /* Fax tone -- Handle and return NULL */ ast_log(LOG_DEBUG, "Fax detected on %s\n", ast_channel_name(chan)); ast_log(LOG_DEBUG, "Fax detected on %s\n", ast_channel_name(chan)); if (strcmp(ast_channel_exten(chan), "fax")) { ast_log(LOG_NOTICE, "Redirecting %s to fax extension\n", ast_channel_name(chan)); pbx_builtin_setvar_helper(chan, "FAX_DETECTED", "1"); pbx_builtin_setvar_helper(chan,"FAXEXTEN",ast_channel_exten(chan)); if (ast_exists_extension(chan, ast_channel_context(chan), "fax", 1, ast_channel_caller(chan)->id.number.str)) { /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ // strncpy(ast_channel_exten(chan), "fax", sizeof(ast_channel_exten(chan))-1); // chan->priority = 0; ast_channel_exten_set(chan, "fax"); ast_channel_priority_set(chan, 0); } else ast_log(LOG_WARNING, "Fax detected, but no fax extension\n"); } else ast_log(LOG_WARNING, "Already in a fax extension, not redirecting\n"); res = 0; ast_frfree(fr); break; } else if (!ignoredtmf) { ast_log(LOG_DEBUG, "DTMF detected on %s\n", ast_channel_name(chan)); char t[2]; t[0] = fr2->subclass.integer; t[1] = '\0'; if (noextneeded || ast_canmatch_extension(chan, ast_channel_context(chan), t, 1, ast_channel_caller(chan)->id.number.str)) { pbx_builtin_setvar_helper(chan, "DTMF_DETECTED", "1"); /* They entered a valid extension, or might be anyhow */ if (noextneeded) { ast_log(LOG_NOTICE, "DTMF received (not matching to exten)\n"); res = 0; } else { ast_log(LOG_NOTICE, "DTMF received (matching to exten)\n"); res = fr2->subclass.integer; } ast_frfree(fr); break; } else ast_log(LOG_DEBUG, "Valid extension requested and DTMF did not match\n"); } // } else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR) && !ignoretalk) { } else if ((fr->frametype == AST_FRAME_VOICE) && ( ast_format_cap_iscompatible(cap, &fr->subclass.format)) && !ignoretalk) { int totalsilence; int ms; res = ast_dsp_silence(dsp, fr, &totalsilence); if (res && (totalsilence > sildur)) { /* We've been quiet a little while */ if (notsilent) { /* We had heard some talking */ gettimeofday(&end, NULL); ms = (end.tv_sec - start.tv_sec) * 1000; ms += (end.tv_usec - start.tv_usec) / 1000; ms -= sildur; if (ms < 0) ms = 0; if ((ms > mindur) && ((maxdur < 0) || (ms < maxdur))) { char ms_str[10]; ast_log(LOG_DEBUG, "Found qualified token of %d ms\n", ms); ast_log(LOG_NOTICE, "Redirecting %s to talk extension\n", ast_channel_name(chan)); /* Save detected talk time (in milliseconds) */ sprintf(ms_str, "%d", ms); pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str); if (ast_exists_extension(chan, ast_channel_context(chan), "talk", 1, ast_channel_caller(chan)->id.number.str)) { // strncpy(ast_channel_exten(chan), "talk", sizeof(ast_channel_exten(chan)) - 1); // chan->priority = 0; ast_channel_exten_set(chan, "talk"); ast_channel_priority_set(chan, 0); } else ast_log(LOG_WARNING, "Talk detected, but no talk extension\n"); res = 0; ast_frfree(fr); break; } else ast_log(LOG_DEBUG, "Found unqualified token of %d ms\n", ms); notsilent = 0; } } else { if (!notsilent) { /* Heard some audio, mark the begining of the token */ gettimeofday(&start, NULL); ast_log(LOG_DEBUG, "Start of voice token!\n"); notsilent = 1; } } } ast_frfree(fr); } } else ast_log(LOG_WARNING, "Could not answer channel '%s'\n", ast_channel_name(chan)); if (res > -1) { if (origrformat && ast_set_read_format(chan, origrformat)) { ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n", ast_channel_name(chan), ast_getformatname(origrformat)); } } if (dsp) ast_dsp_free(dsp); // LOCAL_USER_REMOVE(u); ast_format_cap_destroy(cap); return res; }
int ast_format_cap_has_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) { struct ao2_iterator it; struct ast_format *tmp; struct find_joint_data data = { .joint_found = 0, .joint_cap = NULL, }; it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { data.format = tmp; ao2_callback(cap2->formats, OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock, find_joint_cb, &data); ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return data.joint_found ? 1 : 0; } int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) { struct ao2_iterator it; struct ast_format *tmp; if (ao2_container_count(cap1->formats) != ao2_container_count(cap2->formats)) { return 0; /* if they are not the same size, they are not identical */ } it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { if (!ast_format_cap_iscompatible(cap2, tmp)) { ao2_ref(tmp, -1); ao2_iterator_destroy(&it); return 0; } ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return 1; } struct ast_format_cap *ast_format_cap_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) { struct ao2_iterator it; struct ast_format_cap *result = ast_format_cap_alloc_nolock(); struct ast_format *tmp; struct find_joint_data data = { .joint_found = 0, .joint_cap = result, }; if (!result) { return NULL; } it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { data.format = tmp; ao2_callback(cap2->formats, OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock, find_joint_cb, &data); ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); if (ao2_container_count(result->formats)) { return result; } result = ast_format_cap_destroy(result); return NULL; } static int joint_copy_helper(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result, int append) { struct ao2_iterator it; struct ast_format *tmp; struct find_joint_data data = { .joint_cap = result, .joint_found = 0, }; if (!append) { ast_format_cap_remove_all(result); } it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { data.format = tmp; ao2_callback(cap2->formats, OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock, find_joint_cb, &data); ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return ao2_container_count(result->formats) ? 1 : 0; } int ast_format_cap_joint_append(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result) { return joint_copy_helper(cap1, cap2, result, 1); } int ast_format_cap_joint_copy(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result) { return joint_copy_helper(cap1, cap2, result, 0); } struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap, enum ast_format_type ftype) { struct ao2_iterator it; struct ast_format_cap *result = ast_format_cap_alloc_nolock(); struct ast_format *tmp; if (!result) { return NULL; } /* for each format in cap1, see if that format is * compatible with cap2. If so copy it to the result */ it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { if (AST_FORMAT_GET_TYPE(tmp->id) == ftype) { /* copy format */ ast_format_cap_add(result, tmp); } ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); if (ao2_container_count(result->formats)) { return result; } result = ast_format_cap_destroy(result); return NULL; } int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_format_type type) { struct ao2_iterator it; struct ast_format *tmp; it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { if (AST_FORMAT_GET_TYPE(tmp->id) == type) { ao2_ref(tmp, -1); ao2_iterator_destroy(&it); return 1; } ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return 0; } void ast_format_cap_iter_start(struct ast_format_cap *cap) { if (!cap->nolock) { ao2_lock(cap->formats); } cap->it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); } void ast_format_cap_iter_end(struct ast_format_cap *cap) { ao2_iterator_destroy(&cap->it); if (!cap->nolock) { ao2_unlock(cap->formats); } } int ast_format_cap_iter_next(struct ast_format_cap *cap, struct ast_format *format) { struct ast_format *tmp = ao2_iterator_next(&cap->it); if (!tmp) { return -1; } ast_format_copy(format, tmp); ao2_ref(tmp, -1); return 0; } char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap) { int x; unsigned len; char *start, *end = buf; struct ast_format tmp_fmt; size_t f_len; const struct ast_format_list *f_list = ast_format_list_get(&f_len); if (!size) { f_list = ast_format_list_destroy(f_list); return buf; } snprintf(end, size, "("); len = strlen(end); end += len; size -= len; start = end; for (x = 0; x < f_len; x++) { ast_format_copy(&tmp_fmt, &f_list[x].format); if (ast_format_cap_iscompatible(cap, &tmp_fmt)) { snprintf(end, size, "%s|", f_list[x].name); len = strlen(end); end += len; size -= len; } } if (start == end) { ast_copy_string(start, "nothing)", size); } else if (size > 1) { *(end - 1) = ')'; } f_list = ast_format_list_destroy(f_list); return buf; } uint64_t ast_format_cap_to_old_bitfield(const struct ast_format_cap *cap) { uint64_t res = 0; struct ao2_iterator it; struct ast_format *tmp; it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { res |= ast_format_to_old_bitfield(tmp); ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return res; }