SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *bug, switch_frame_t *frame, switch_bool_t fill) { switch_size_t bytes = 0, datalen = 0, ttl = 0; int16_t *dp, *fp; uint32_t x; size_t rlen = 0; size_t wlen = 0; uint32_t blen; switch_codec_implementation_t read_impl = { 0 }; int16_t *tp; switch_core_session_get_read_impl(bug->session, &read_impl); bytes = read_impl.decoded_bytes_per_packet; if (frame->buflen < bytes) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "%s frame buffer too small!\n", switch_channel_get_name(bug->session->channel)); return SWITCH_STATUS_FALSE; } if (!(bug->raw_read_buffer && (bug->raw_write_buffer || !switch_test_flag(bug, SMBF_WRITE_STREAM)))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "%s Buffer Error\n", switch_channel_get_name(bug->session->channel)); return SWITCH_STATUS_FALSE; } frame->flags = 0; frame->datalen = 0; if (!switch_buffer_inuse(bug->raw_read_buffer)) { return SWITCH_STATUS_FALSE; } switch_mutex_lock(bug->read_mutex); frame->datalen = (uint32_t) switch_buffer_read(bug->raw_read_buffer, frame->data, bytes); ttl += frame->datalen; switch_mutex_unlock(bug->read_mutex); if (switch_test_flag(bug, SMBF_WRITE_STREAM)) { switch_assert(bug->raw_write_buffer); switch_mutex_lock(bug->write_mutex); datalen = (uint32_t) switch_buffer_read(bug->raw_write_buffer, bug->data, bytes); ttl += datalen; if (fill && datalen < bytes) { memset(((unsigned char *) bug->data) + datalen, 0, bytes - datalen); datalen = bytes; } switch_mutex_unlock(bug->write_mutex); } tp = bug->tmp; dp = (int16_t *) bug->data; fp = (int16_t *) frame->data; rlen = frame->datalen / 2; wlen = datalen / 2; blen = bytes / 2; if (!fill && rlen == 0 && wlen == 0) { frame->datalen = 0; frame->samples = 0; frame->rate = read_impl.actual_samples_per_second; frame->codec = NULL; return SWITCH_STATUS_FALSE; } if (switch_test_flag(bug, SMBF_STEREO)) { for (x = 0; x < blen; x++) { if (x < rlen) { *(tp++) = *(fp + x); } else { *(tp++) = 0; } if (x < wlen) { *(tp++) = *(dp + x); } else { *(tp++) = 0; } } memcpy(frame->data, bug->tmp, bytes * 2); } else { for (x = 0; x < blen; x++) { int32_t z = 0; if (x < rlen) { z += (int32_t) * (fp + x); } if (x < wlen) { z += (int32_t) * (dp + x); } switch_normalize_to_16bit(z); *(fp + x) = (int16_t) z / 2; } } if (!ttl) { switch_set_flag(frame, SFF_CNG); } frame->datalen = bytes; frame->samples = bytes / sizeof(int16_t); frame->rate = read_impl.actual_samples_per_second; frame->codec = NULL; return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session, const char *function, const char *target, switch_media_bug_callback_t callback, void *user_data, time_t stop_time, switch_media_bug_flag_t flags, switch_media_bug_t **new_bug) { switch_media_bug_t *bug, *bp; switch_size_t bytes; switch_event_t *event; int tap_only = 1, punt = 0; const char *p; if (!zstr(function)) { if ((flags & SMBF_ONE_ONLY)) { switch_thread_rwlock_wrlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (!zstr(bp->function) && !strcasecmp(function, bp->function)) { punt = 1; break; } } switch_thread_rwlock_unlock(session->bug_rwlock); } } if (punt) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); return SWITCH_STATUS_GENERR; } if (!switch_channel_media_ready(session->channel)) { if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_FALSE; } } *new_bug = NULL; if ((p = switch_channel_get_variable(session->channel, "media_bug_answer_req")) && switch_true(p)) { flags |= SMBF_ANSWER_REQ; } #if 0 if (flags & SMBF_WRITE_REPLACE) { switch_thread_rwlock_wrlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); switch_thread_rwlock_unlock(session->bug_rwlock); return SWITCH_STATUS_GENERR; } } switch_thread_rwlock_unlock(session->bug_rwlock); } if (flags & SMBF_READ_REPLACE) { switch_thread_rwlock_wrlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_test_flag(bp, SMBF_READ_REPLACE)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); switch_thread_rwlock_unlock(session->bug_rwlock); return SWITCH_STATUS_GENERR; } } switch_thread_rwlock_unlock(session->bug_rwlock); } #endif if (!(bug = switch_core_session_alloc(session, sizeof(*bug)))) { return SWITCH_STATUS_MEMERR; } bug->callback = callback; bug->user_data = user_data; bug->session = session; bug->flags = flags; bug->function = "N/A"; bug->target = "N/A"; switch_core_session_get_read_impl(session, &bug->read_impl); switch_core_session_get_write_impl(session, &bug->write_impl); if (function) { bug->function = switch_core_session_strdup(session, function); } if (target) { bug->target = switch_core_session_strdup(session, target); } bug->stop_time = stop_time; bytes = bug->read_impl.decoded_bytes_per_packet; if (!bug->flags) { bug->flags = (SMBF_READ_STREAM | SMBF_WRITE_STREAM); } if (switch_test_flag(bug, SMBF_READ_STREAM) || switch_test_flag(bug, SMBF_READ_PING)) { switch_buffer_create_dynamic(&bug->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER); switch_mutex_init(&bug->read_mutex, SWITCH_MUTEX_NESTED, session->pool); } bytes = bug->write_impl.decoded_bytes_per_packet; if (switch_test_flag(bug, SMBF_WRITE_STREAM)) { switch_buffer_create_dynamic(&bug->raw_write_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER); switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool); } if ((bug->flags & SMBF_THREAD_LOCK)) { bug->thread_id = switch_thread_self(); } if (bug->callback) { switch_bool_t result = bug->callback(bug, bug->user_data, SWITCH_ABC_TYPE_INIT); if (result == SWITCH_FALSE) { switch_core_media_bug_destroy(bug); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error attaching BUG to %s\n", switch_channel_get_name(session->channel)); return SWITCH_STATUS_GENERR; } } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Attaching BUG to %s\n", switch_channel_get_name(session->channel)); bug->ready = 1; switch_thread_rwlock_wrlock(session->bug_rwlock); bug->next = session->bugs; session->bugs = bug; for(bp = session->bugs; bp; bp = bp->next) { if (bp->ready && !switch_test_flag(bp, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp, SMBF_TAP_NATIVE_WRITE)) { tap_only = 0; } } switch_thread_rwlock_unlock(session->bug_rwlock); *new_bug = bug; if (tap_only) { switch_set_flag(session, SSF_MEDIA_BUG_TAP_ONLY); } else { switch_clear_flag(session, SSF_MEDIA_BUG_TAP_ONLY); } if (switch_event_create(&event, SWITCH_EVENT_MEDIA_BUG_START) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bug->function); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bug->target); switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj) { int reps = 0, errs = 0, timeouts = 0, match = 0, running = 1; char *greeting_sound = NULL, *aptr = NULL; char arg[512]; switch_ivr_action_t todo = SWITCH_IVR_ACTION_DIE; switch_ivr_menu_action_t *ap; switch_ivr_menu_t *menu; switch_channel_t *channel; switch_status_t status = SWITCH_STATUS_SUCCESS; if (++stack->stack_count > 12) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Too many levels of recursion.\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } if (!session || !stack || zstr(name)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid menu context\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } channel = switch_core_session_get_channel(session); if (!(menu = switch_ivr_menu_find(stack, name))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Menu!\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) { switch_channel_set_variable(channel, "tts_engine", menu->tts_engine); switch_channel_set_variable(channel, "tts_voice", menu->tts_voice); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name); switch_channel_set_variable(channel, "ivr_menu_status", "success"); if (!zstr(menu->pin)) { char digit_buffer[128] = ""; char *digits_regex = switch_core_session_sprintf(session, "^%s$", menu->pin); if (switch_play_and_get_digits(session, strlen(menu->pin), strlen(menu->pin), 3, 3000, "#", menu->prompt_pin_file, menu->bad_pin_file, NULL, digit_buffer, sizeof(digit_buffer), digits_regex, 10000, NULL) != SWITCH_STATUS_SUCCESS) { switch_goto_status(SWITCH_STATUS_FALSE, end); } } for (reps = 0; running && status == SWITCH_STATUS_SUCCESS; reps++) { if (!switch_channel_ready(channel)) { break; } if (errs == menu->max_failures) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum failures\n"); switch_channel_set_variable(channel, "ivr_menu_status", "failure"); if (!zstr(menu->exec_on_max_fail)) { exec_app(session, menu->exec_on_max_fail); } break; } if (timeouts == menu->max_timeouts) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum timeouts\n"); switch_channel_set_variable(channel, "ivr_menu_status", "timeout"); if (!zstr(menu->exec_on_max_timeout)) { exec_app(session, menu->exec_on_max_timeout); } break; } if (reps > 0 && menu->short_greeting_sound) { greeting_sound = menu->short_greeting_sound; } else { greeting_sound = menu->greeting_sound; } match = 0; aptr = NULL; memset(arg, 0, sizeof(arg)); memset(menu->buf, 0, menu->inlen + 1); if (play_and_collect(session, menu, greeting_sound, menu->inlen) == SWITCH_STATUS_TIMEOUT && *menu->buf == '\0') { timeouts++; continue; } if (*menu->buf != '\0') { for (ap = menu->actions; ap; ap = ap->next) { int ok = 0; char substituted[1024]; char *use_arg = ap->arg; if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) { switch_channel_set_variable(channel, "tts_engine", menu->tts_engine); switch_channel_set_variable(channel, "tts_voice", menu->tts_voice); } if (ap->re) { switch_regex_t *re = NULL; int ovector[30]; if ((ok = switch_regex_perform(menu->buf, ap->bind, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_perform_substitution(re, ok, ap->arg, menu->buf, substituted, sizeof(substituted), ovector); use_arg = substituted; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "action regex [%s] [%s] [%d]\n", menu->buf, ap->bind, ok); switch_regex_safe_free(re); } else { ok = !strcmp(menu->buf, ap->bind); } if (ok) { match++; errs = 0; if (ap->function) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR function on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, use_arg); todo = ap->function(menu, use_arg, arg, sizeof(arg), obj); aptr = arg; } else { todo = ap->ivr_action; aptr = use_arg; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR action on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, aptr); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "switch_ivr_menu_execute todo=[%d]\n", todo); switch (todo) { case SWITCH_IVR_ACTION_DIE: status = SWITCH_STATUS_FALSE; break; case SWITCH_IVR_ACTION_PLAYSOUND: status = switch_ivr_play_file(session, NULL, aptr, NULL); break; case SWITCH_IVR_ACTION_EXECMENU: if (!strcmp(aptr, menu->name)) { status = SWITCH_STATUS_SUCCESS; } else { reps = -1; status = switch_ivr_menu_execute(session, stack, aptr, obj); } break; case SWITCH_IVR_ACTION_EXECAPP: { switch_application_interface_t *application_interface; char *app_name; char *app_arg = NULL; status = SWITCH_STATUS_FALSE; if (!zstr(aptr)) { app_name = switch_core_session_strdup(session, aptr); if ((app_arg = strchr(app_name, ' '))) { *app_arg++ = '\0'; } if ((application_interface = switch_loadable_module_get_application_interface(app_name))) { if (!zstr(menu->transfer_sound) && !strcmp(app_name, "transfer")) { status = play_and_collect(session, menu, menu->transfer_sound, 0); } switch_core_session_exec(session, application_interface, app_arg); UNPROTECT_INTERFACE(application_interface); status = SWITCH_STATUS_SUCCESS; } } } break; case SWITCH_IVR_ACTION_BACK: running = 0; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_IVR_ACTION_TOMAIN: switch_set_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN); status = SWITCH_STATUS_BREAK; break; case SWITCH_IVR_ACTION_NOOP: status = SWITCH_STATUS_SUCCESS; break; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid TODO!\n"); break; } } } if (switch_test_flag(menu, SWITCH_IVR_MENU_FLAG_STACK)) { /* top level */ if (switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN)) { /* catch the fallback and recover */ switch_clear_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN); status = SWITCH_STATUS_SUCCESS; running = 1; continue; } } } if (!match) { if (*menu->buf) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' caught invalid input '%s'\n", menu->name, menu->buf); if (menu->invalid_sound) { play_and_collect(session, menu, menu->invalid_sound, 0); } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' no input detected\n", menu->name); } errs++; /* breaks are ok too */ if (SWITCH_STATUS_IS_BREAK(status)) { status = SWITCH_STATUS_SUCCESS; } } } if (stack->stack_count == 1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "exit-sound '%s'\n", menu->exit_sound); if (!zstr(menu->exit_sound)) { status = play_and_collect(session, menu, menu->exit_sound, 0); } } end: stack->stack_count--; return status; }
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; }
static switch_status_t shout_file_open(switch_file_handle_t *handle, const char *path) { shout_context_t *context; char *host, *file; char *username, *password, *port; char *err = NULL; const char *mpg123err = NULL; int portno = 0; if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) { return SWITCH_STATUS_MEMERR; } if (!handle->samplerate) { handle->samplerate = 8000; } context->memory_pool = handle->memory_pool; context->samplerate = handle->samplerate; context->handle = handle; switch_thread_rwlock_create(&(context->rwlock), context->memory_pool); switch_thread_rwlock_rdlock(context->rwlock); switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->memory_pool); if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) { if (switch_buffer_create_dynamic(&context->audio_buffer, TC_BUFFER_SIZE, TC_BUFFER_SIZE * 2, 0) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); goto error; } context->mh = our_mpg123_new(NULL, NULL); if (mpg123_format_all(context->mh) != MPG123_OK) { MPGERROR(); } if (mpg123_param(context->mh, MPG123_FORCE_RATE, context->samplerate, 0) != MPG123_OK) { MPGERROR(); } if (handle->handler) { if (mpg123_param(context->mh, MPG123_FLAGS, MPG123_SEEKBUFFER | MPG123_MONO_MIX, 0) != MPG123_OK) { MPGERROR(); } if (mpg123_open_feed(context->mh) != MPG123_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening mpg feed\n"); mpg123err = mpg123_strerror(context->mh); goto error; } context->stream_url = switch_core_sprintf(context->memory_pool, "http://%s", path); context->prebuf = handle->prebuf; launch_read_stream_thread(context); } else { handle->seekable = 1; if (mpg123_param(context->mh, MPG123_FLAGS, MPG123_MONO_MIX, 0) != MPG123_OK) { MPGERROR(); } if (mpg123_open(context->mh, path) != MPG123_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path); mpg123err = mpg123_strerror(context->mh); goto error; } } } else if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) { if (!(context->gfp = lame_init())) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n"); goto error; } if (!handle->handler) { id3tag_init(context->gfp); id3tag_v2_only(context->gfp); id3tag_pad_v2(context->gfp); } context->channels = handle->channels; if (globals.brate) { lame_set_brate(context->gfp, globals.brate); } else { lame_set_brate(context->gfp, 16 * (handle->samplerate / 8000) * handle->channels); } lame_set_num_channels(context->gfp, handle->channels); lame_set_in_samplerate(context->gfp, handle->samplerate); if (globals.resample) { lame_set_out_samplerate(context->gfp, globals.resample); } else { lame_set_out_samplerate(context->gfp, handle->samplerate); } if (handle->channels == 2) { lame_set_mode(context->gfp, STEREO); } else { lame_set_mode(context->gfp, MONO); } if (globals.quality) { lame_set_quality(context->gfp, globals.quality); } else { lame_set_quality(context->gfp, 2); /* 2=high 5 = medium 7=low */ } lame_set_errorf(context->gfp, log_error); lame_set_debugf(context->gfp, log_debug); lame_set_msgf(context->gfp, log_msg); if (handle->handler) { if (switch_buffer_create_dynamic(&context->audio_buffer, MY_BLOCK_SIZE, MY_BUF_LEN, 0) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); goto error; } lame_set_bWriteVbrTag(context->gfp, 0); lame_mp3_tags_fid(context->gfp, NULL); username = switch_core_strdup(handle->memory_pool, path); if (!(password = strchr(username, ':'))) { err = "invalid url"; goto error; } *password++ = '\0'; if (!(host = strchr(password, '@'))) { err = "invalid url"; goto error; } *host++ = '\0'; if ((file = strchr(host, '/'))) { *file++ = '\0'; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid URL: %s\n", path); goto error; } if ((port = strchr(host, ':'))) { *port++ = '\0'; if (port) { portno = atoi(port); } } if (!portno) { portno = 8000; } if (!(context->shout = shout_new())) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate shout_t\n"); goto error; } if (shout_set_host(context->shout, host) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting hostname: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_protocol(context->shout, SHOUT_PROTOCOL_HTTP) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting protocol: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_port(context->shout, portno) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting port: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_password(context->shout, password) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting password: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_mount(context->shout, file) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting mount: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_user(context->shout, username) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting user: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_url(context->shout, "http://www.freeswitch.org") != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_description(context->shout, "FreeSWITCH mod_shout Broadcasting Module") != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting description: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_audio_info(context->shout, "bitrate", "24000") != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting bitrate: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_format(context->shout, SHOUT_FORMAT_MP3) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting format: %s\n", shout_get_error(context->shout)); goto error; } } else { const char *mask = "wb+"; if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND)) { mask = "ab+"; } /* lame being lame and all has FILE * coded into it's API for some functions so we gotta use it */ if (!(context->fp = fopen(path, mask))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path); goto error; } if (!context->lame_ready) { lame_init_params(context->gfp); lame_print_config(context->gfp); context->lame_ready = 1; } } } handle->samples = 0; handle->format = 0; handle->sections = 0; handle->speed = 0; handle->private_info = context; switch_thread_rwlock_unlock(context->rwlock); return SWITCH_STATUS_SUCCESS; error: switch_thread_rwlock_unlock(context->rwlock); if (err) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: %s\n", err); } if (mpg123err) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error from mpg123: %s\n", mpg123err); } free_context(context); return SWITCH_STATUS_GENERR; }
/** * 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) { 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"); if (!zstr(id)) { context->id = switch_core_strdup(handle->memory_pool, id); } if (!zstr(uuid)) { context->uuid = switch_core_strdup(handle->memory_pool, uuid); } } 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); } return status; }
/** * Process fileman command */ static switch_status_t fileman_process_cmd(const char *cmd, switch_file_handle_t *fhp) { if (zstr(cmd)) { return SWITCH_STATUS_SUCCESS; } if (fhp) { if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { return SWITCH_STATUS_FALSE; } if (!strncasecmp(cmd, "speed", 5)) { char *p; if ((p = strchr(cmd, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { if (*p == '+') { step = 1; } else { step = -1; } } fhp->speed += step; } else { int speed = atoi(p); fhp->speed = speed; } return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; } else if (!strncasecmp(cmd, "volume", 6)) { char *p; if ((p = strchr(cmd, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { if (*p == '+') { step = 1; } else { step = -1; } } fhp->vol += step; } else { int vol = atoi(p); fhp->vol = vol; } return SWITCH_STATUS_SUCCESS; } if (fhp->vol) { switch_normalize_volume(fhp->vol); } return SWITCH_STATUS_FALSE; } else if (!strcasecmp(cmd, "pause")) { switch_set_flag(fhp, SWITCH_FILE_PAUSE); return SWITCH_STATUS_SUCCESS; } else if (!strcasecmp(cmd, "resume")) { switch_clear_flag(fhp, SWITCH_FILE_PAUSE); return SWITCH_STATUS_SUCCESS; } else if (!strcasecmp(cmd, "stop")) { switch_set_flag(fhp, SWITCH_FILE_DONE); return SWITCH_STATUS_FALSE; } else if (!strcasecmp(cmd, "truncate")) { switch_core_file_truncate(fhp, 0); } else if (!strcasecmp(cmd, "restart")) { unsigned int pos = 0; fhp->speed = 0; switch_core_file_seek(fhp, &pos, 0, SEEK_SET); return SWITCH_STATUS_SUCCESS; } else if (!strncasecmp(cmd, "seek", 4)) { unsigned int samps = 0; unsigned int pos = 0; char *p; if ((p = strchr(cmd, ':'))) { p++; if (*p == '+' || *p == '-') { int step; int32_t target; if (!(step = atoi(p))) { if (*p == '+') { step = 1000; } else { step = -1000; } } samps = step * (fhp->samplerate / 1000); target = (int32_t)fhp->pos + samps; if (target < 0) { target = 0; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "seek to position %d\n", target); switch_core_file_seek(fhp, &pos, target, SEEK_SET); } else { samps = switch_atoui(p) * (fhp->samplerate / 1000); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "seek to position %d\n", samps); switch_core_file_seek(fhp, &pos, samps, SEEK_SET); } } return SWITCH_STATUS_SUCCESS; } } if (!strcmp(cmd, "true") || !strcmp(cmd, "undefined")) { return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }
SWITCH_DECLARE(void) switch_core_session_hangup_state(switch_core_session_t *session, switch_bool_t force) { switch_call_cause_t cause = switch_channel_get_cause(session->channel); switch_call_cause_t cause_q850 = switch_channel_get_cause_q850(session->channel); int proceed = 1; int global_proceed = 1; int do_extra_handlers = 1; int silly = 0; int index = 0; switch_channel_state_t state = switch_channel_get_state(session->channel), midstate = state; const switch_endpoint_interface_t *endpoint_interface; const switch_state_handler_table_t *driver_state_handler = NULL; const switch_state_handler_table_t *application_state_handler = NULL; const char *hook_var; int use_session = 0; if (!force) { if (!switch_channel_test_flag(session->channel, CF_EARLY_HANGUP) && !switch_test_flag((&runtime), SCF_EARLY_HANGUP)) { return; } if (switch_thread_self() != session->thread_id) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "%s thread mismatch skipping state handler.\n", switch_channel_get_name(session->channel)); return; } } if (switch_test_flag(session, SSF_HANGUP)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "%s handler already called, skipping state handler.\n", switch_channel_get_name(session->channel)); return; } endpoint_interface = session->endpoint_interface; switch_assert(endpoint_interface != NULL); driver_state_handler = endpoint_interface->state_handler; switch_assert(driver_state_handler != NULL); switch_channel_set_hangup_time(session->channel); switch_core_media_bug_remove_all(session); switch_channel_stop_broadcast(session->channel); switch_channel_set_variable(session->channel, "hangup_cause", switch_channel_cause2str(cause)); switch_channel_set_variable_printf(session->channel, "hangup_cause_q850", "%d", cause_q850); //switch_channel_presence(session->channel, "unknown", switch_channel_cause2str(cause), NULL); switch_channel_set_timestamps(session->channel); STATE_MACRO(hangup, "HANGUP"); if ((hook_var = switch_channel_get_variable(session->channel, SWITCH_API_HANGUP_HOOK_VARIABLE))) { if (switch_true(switch_channel_get_variable(session->channel, SWITCH_SESSION_IN_HANGUP_HOOK_VARIABLE))) { use_session = 1; } api_hook(session, hook_var, use_session); } switch_set_flag(session, SSF_HANGUP); }
static int task_thread_loop(int done) { switch_scheduler_task_container_t *tofree, *tp, *last = NULL; switch_mutex_lock(globals.task_mutex); for (tp = globals.task_list; tp; tp = tp->next) { if (done) { tp->destroyed = 1; } else if (!tp->destroyed) { int64_t now = switch_epoch_time_now(NULL); if (now >= tp->task.runtime && !tp->in_thread) { int32_t diff = (int32_t) (now - tp->task.runtime); if (diff > 1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Task was executed late by %d seconds %u %s (%s)\n", diff, tp->task.task_id, tp->desc, switch_str_nil(tp->task.group)); } tp->executed = now; if (switch_test_flag(tp, SSHF_OWN_THREAD)) { switch_thread_t *thread; switch_threadattr_t *thd_attr; switch_core_new_memory_pool(&tp->pool); switch_threadattr_create(&thd_attr, tp->pool); switch_threadattr_detach_set(thd_attr, 1); tp->in_thread = 1; switch_thread_create(&thread, thd_attr, task_own_thread, tp, tp->pool); } else { switch_scheduler_execute(tp); } } } } switch_mutex_unlock(globals.task_mutex); switch_mutex_lock(globals.task_mutex); for (tp = globals.task_list; tp;) { if (tp->destroyed && !tp->in_thread) { tofree = tp; tp = tp->next; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleting task %u %s (%s)\n", tofree->task.task_id, tofree->desc, switch_str_nil(tofree->task.group)); if (last) { last->next = tofree->next; } else { globals.task_list = tofree->next; } switch_safe_free(tofree->task.group); if (tofree->task.cmd_arg && switch_test_flag(tofree, SSHF_FREE_ARG)) { free(tofree->task.cmd_arg); } switch_safe_free(tofree->desc); free(tofree); } else { last = tp; tp = tp->next; } } switch_mutex_unlock(globals.task_mutex); return done; }
static switch_bool_t stop_detect(pocketsphinx_t *ps, int16_t *data, unsigned int samples) { uint32_t score, count = 0, j = 0; double energy = 0; if (ps->countdown) { if (!--ps->countdown) { ps->silence_hits = ps->org_silence_hits; ps->listening = 0; return SWITCH_TRUE; } return SWITCH_FALSE; } /* Do simple energy threshold for VAD */ for (count = 0; count < samples; count++) { energy += abs(data[j]); } score = (uint32_t) (energy / samples); if (score >= ps->thresh) { if (++ps->listening == 1) { switch_mutex_lock(ps->flag_mutex); switch_set_flag(ps, PSFLAG_BARGE); switch_set_flag(ps, PSFLAG_START_OF_SPEECH); switch_mutex_unlock(ps->flag_mutex); } ps->silence_time = 0; } else if (!ps->silence_time) { ps->silence_time = switch_micro_time_now(); } /* Check silence timeouts */ if (ps->silence_time && switch_test_flag(ps, PSFLAG_INPUT_TIMERS)) { int elapsed_ms = (switch_micro_time_now() - ps->silence_time) / 1000; if (switch_test_flag(ps, PSFLAG_START_OF_SPEECH)) { if (ps->speech_timeout > 0 && !switch_test_flag(ps, PSFLAG_SPEECH_TIMEOUT) && elapsed_ms >= ps->speech_timeout) { switch_set_flag_locked(ps, PSFLAG_SPEECH_TIMEOUT); ps->listening = 0; return SWITCH_TRUE; } } else { if (ps->no_input_timeout > 0 && !switch_test_flag(ps, PSFLAG_NOINPUT_TIMEOUT) && elapsed_ms >= ps->no_input_timeout) { switch_mutex_lock(ps->flag_mutex); switch_set_flag(ps, PSFLAG_NOINPUT_TIMEOUT); switch_set_flag(ps, PSFLAG_NOINPUT); switch_mutex_unlock(ps->flag_mutex); ps->listening = 0; return SWITCH_TRUE; } } } if (ps->listening > ps->listen_hits && score < ps->thresh) { if (!--ps->silence_hits) { ps->countdown = 12; } } else { ps->silence_hits = ps->org_silence_hits; } return SWITCH_FALSE; }
/*! function to feed audio to the ASR */ static switch_status_t pocketsphinx_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags) { pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info; int rv = 0; if (switch_test_flag(ah, SWITCH_ASR_FLAG_CLOSED)) return SWITCH_STATUS_BREAK; if (!switch_test_flag(ps, PSFLAG_NOMATCH) && !switch_test_flag(ps, PSFLAG_NOINPUT) && !switch_test_flag(ps, PSFLAG_HAS_TEXT) && switch_test_flag(ps, PSFLAG_READY)) { if (stop_detect(ps, (int16_t *) data, len / 2)) { char const *hyp; switch_mutex_lock(ps->flag_mutex); if ((hyp = ps_get_hyp(ps->ps, &ps->score, &ps->uttid))) { if (!zstr(hyp)) { ps_end_utt(ps->ps); switch_clear_flag(ps, PSFLAG_READY); if ((hyp = ps_get_hyp(ps->ps, &ps->score, &ps->uttid))) { if (zstr(hyp)) { if (!switch_test_flag(ps, PSFLAG_SPEECH_TIMEOUT)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Lost the text, never mind....\n"); ps_start_utt(ps->ps, NULL); switch_set_flag(ps, PSFLAG_READY); } } else { /* get match and confidence */ int32_t conf; conf = ps_get_prob(ps->ps, &ps->uttid); ps->confidence = (conf + 20000) / 200; if (ps->confidence < 0) { ps->confidence = 0; } if (ps->confidence_threshold <= 0 || ps->confidence >= ps->confidence_threshold) { ps->hyp = switch_core_strdup(ah->memory_pool, hyp); switch_set_flag(ps, PSFLAG_HAS_TEXT); } else { /* have match, but below confidence threshold */ switch_set_flag(ps, PSFLAG_NOMATCH); } } } } } if (switch_test_flag(ps, PSFLAG_SPEECH_TIMEOUT) && !switch_test_flag(ps, PSFLAG_HAS_TEXT)) { /* heard something, but doesn't match anything */ switch_clear_flag(ps, PSFLAG_READY); switch_set_flag(ps, PSFLAG_NOMATCH); } switch_mutex_unlock(ps->flag_mutex); } /* only feed ps_process_raw when we are listening */ if (ps->listening) { switch_mutex_lock(ps->flag_mutex); rv = ps_process_raw(ps->ps, (int16 *) data, len / 2, FALSE, FALSE); switch_mutex_unlock(ps->flag_mutex); } if (rv < 0) { return SWITCH_STATUS_FALSE; } } else if (switch_test_flag(ps, PSFLAG_NOINPUT_TIMEOUT)) { /* never heard anything */ switch_clear_flag_locked(ps, PSFLAG_READY); } return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) { switch_status_t status = SWITCH_STATUS_FALSE; switch_frame_t *enc_frame = NULL, *write_frame = frame; unsigned int flag = 0, need_codec = 0, perfect = 0, do_bugs = 0, do_write = 0, do_resample = 0, ptime_mismatch = 0, pass_cng = 0, resample = 0; int did_write_resample = 0; switch_assert(session != NULL); switch_assert(frame != NULL); if (!switch_channel_ready(session->channel)) { return SWITCH_STATUS_FALSE; } if (switch_mutex_trylock(session->codec_write_mutex) == SWITCH_STATUS_SUCCESS) { switch_mutex_unlock(session->codec_write_mutex); } else { return SWITCH_STATUS_SUCCESS; } if (switch_test_flag(frame, SFF_CNG)) { if (switch_channel_test_flag(session->channel, CF_ACCEPT_CNG)) { pass_cng = 1; } else { return SWITCH_STATUS_SUCCESS; } } if (!(session->write_codec && switch_core_codec_ready(session->write_codec)) && !pass_cng) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no write codec.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); return SWITCH_STATUS_FALSE; } if (switch_channel_test_flag(session->channel, CF_HOLD)) { return SWITCH_STATUS_SUCCESS; } if (switch_test_flag(frame, SFF_PROXY_PACKET) || pass_cng) { /* Fast PASS! */ switch_mutex_lock(session->codec_write_mutex); status = perform_write(session, frame, flag, stream_id); switch_mutex_unlock(session->codec_write_mutex); return status; } switch_mutex_lock(session->codec_write_mutex); if (!(frame->codec && frame->codec->implementation)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has received a bad frame with no codec!\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_mutex_unlock(session->codec_write_mutex); return SWITCH_STATUS_FALSE; } switch_assert(frame->codec != NULL); switch_assert(frame->codec->implementation != NULL); if (!(switch_core_codec_ready(session->write_codec) && frame->codec) || !switch_channel_ready(session->channel) || !switch_channel_media_ready(session->channel)) { switch_mutex_unlock(session->codec_write_mutex); return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->write_codec->mutex); switch_mutex_lock(frame->codec->mutex); if (!(switch_core_codec_ready(session->write_codec) && switch_core_codec_ready(frame->codec))) goto error; if ((session->write_codec && frame->codec && session->write_codec->implementation != frame->codec->implementation)) { if (session->write_impl.codec_id == frame->codec->implementation->codec_id || session->write_impl.microseconds_per_packet != frame->codec->implementation->microseconds_per_packet) { ptime_mismatch = TRUE; if ((switch_test_flag(frame->codec, SWITCH_CODEC_FLAG_PASSTHROUGH) || switch_test_flag(session->read_codec, SWITCH_CODEC_FLAG_PASSTHROUGH)) || switch_channel_test_flag(session->channel, CF_PASSTHRU_PTIME_MISMATCH)) { status = perform_write(session, frame, flags, stream_id); goto error; } } need_codec = TRUE; } if (session->write_codec && !frame->codec) { need_codec = TRUE; } if (session->bugs && !need_codec) { do_bugs = TRUE; need_codec = TRUE; } if (frame->codec->implementation->actual_samples_per_second != session->write_impl.actual_samples_per_second) { need_codec = TRUE; do_resample = TRUE; } if (switch_test_flag(session, SSF_WRITE_TRANSCODE) && !need_codec && switch_core_codec_ready(session->write_codec)) { switch_core_session_t *other_session; const char *uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_SIGNAL_BOND_VARIABLE); if (uuid && (other_session = switch_core_session_locate(uuid))) { switch_set_flag(other_session, SSF_READ_CODEC_RESET); switch_set_flag(other_session, SSF_READ_CODEC_RESET); switch_set_flag(other_session, SSF_WRITE_CODEC_RESET); switch_core_session_rwunlock(other_session); } switch_clear_flag(session, SSF_WRITE_TRANSCODE); } if (switch_test_flag(session, SSF_WRITE_CODEC_RESET)) { switch_core_codec_reset(session->write_codec); switch_clear_flag(session, SSF_WRITE_CODEC_RESET); } if (!need_codec) { do_write = TRUE; write_frame = frame; goto done; } if (!switch_test_flag(session, SSF_WARN_TRANSCODE)) { switch_core_session_message_t msg = { 0 }; msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY; switch_core_session_receive_message(session, &msg); switch_set_flag(session, SSF_WARN_TRANSCODE); } if (frame->codec) { session->raw_write_frame.datalen = session->raw_write_frame.buflen; status = switch_core_codec_decode(frame->codec, session->write_codec, frame->data, frame->datalen, session->write_impl.actual_samples_per_second, session->raw_write_frame.data, &session->raw_write_frame.datalen, &session->raw_write_frame.rate, &frame->flags); if (do_resample && status == SWITCH_STATUS_SUCCESS) { status = SWITCH_STATUS_RESAMPLE; } switch (status) { case SWITCH_STATUS_RESAMPLE: resample++; write_frame = &session->raw_write_frame; write_frame->rate = frame->codec->implementation->actual_samples_per_second; if (!session->write_resampler) { switch_mutex_lock(session->resample_mutex); status = switch_resample_create(&session->write_resampler, frame->codec->implementation->actual_samples_per_second, session->write_impl.actual_samples_per_second, session->write_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1); switch_mutex_unlock(session->resample_mutex); if (status != SWITCH_STATUS_SUCCESS) { goto done; } } break; case SWITCH_STATUS_SUCCESS: session->raw_write_frame.samples = session->raw_write_frame.datalen / sizeof(int16_t); session->raw_write_frame.timestamp = frame->timestamp; session->raw_write_frame.rate = frame->rate; session->raw_write_frame.m = frame->m; session->raw_write_frame.ssrc = frame->ssrc; session->raw_write_frame.seq = frame->seq; session->raw_write_frame.payload = frame->payload; session->raw_write_frame.flags = 0; if (switch_test_flag(frame, SFF_PLC)) { session->raw_write_frame.flags |= SFF_PLC; } write_frame = &session->raw_write_frame; break; case SWITCH_STATUS_BREAK: status = SWITCH_STATUS_SUCCESS; goto error; case SWITCH_STATUS_NOOP: if (session->write_resampler) { switch_mutex_lock(session->resample_mutex); switch_resample_destroy(&session->write_resampler); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n"); switch_mutex_unlock(session->resample_mutex); } write_frame = frame; status = SWITCH_STATUS_SUCCESS; break; default: if (status == SWITCH_STATUS_NOT_INITALIZED) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n"); goto error; } if (ptime_mismatch) { status = perform_write(session, frame, flags, stream_id); status = SWITCH_STATUS_SUCCESS; goto error; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error!\n", frame->codec->codec_interface->interface_name); goto error; } } if (session->write_resampler) { short *data = write_frame->data; switch_mutex_lock(session->resample_mutex); if (session->write_resampler) { switch_resample_process(session->write_resampler, data, write_frame->datalen / 2); memcpy(data, session->write_resampler->to, session->write_resampler->to_len * 2); write_frame->samples = session->write_resampler->to_len; write_frame->datalen = write_frame->samples * 2; write_frame->rate = session->write_resampler->to_rate; did_write_resample = 1; } switch_mutex_unlock(session->resample_mutex); } if (session->bugs) { switch_media_bug_t *bp; int prune = 0; switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { switch_bool_t ok = SWITCH_TRUE; if (!bp->ready) { continue; } if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) { continue; } if (switch_test_flag(bp, SMBF_PRUNE)) { prune++; continue; } if (switch_test_flag(bp, SMBF_WRITE_STREAM)) { switch_mutex_lock(bp->write_mutex); switch_buffer_write(bp->raw_write_buffer, write_frame->data, write_frame->datalen); switch_mutex_unlock(bp->write_mutex); if (bp->callback) { ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE); } } if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) { do_bugs = 0; if (bp->callback) { bp->write_replace_frame_in = write_frame; bp->write_replace_frame_out = write_frame; if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE_REPLACE)) == SWITCH_TRUE) { write_frame = bp->write_replace_frame_out; } } } if (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) { ok = SWITCH_FALSE; } if (ok == SWITCH_FALSE) { switch_set_flag(bp, SMBF_PRUNE); prune++; } } switch_thread_rwlock_unlock(session->bug_rwlock); if (prune) { switch_core_media_bug_prune(session); } } if (do_bugs) { do_write = TRUE; write_frame = frame; goto done; } if (session->write_codec) { if (!ptime_mismatch && write_frame->codec && write_frame->codec->implementation && write_frame->codec->implementation->decoded_bytes_per_packet == session->write_impl.decoded_bytes_per_packet) { perfect = TRUE; } if (perfect) { if (write_frame->datalen < session->write_impl.decoded_bytes_per_packet) { memset(write_frame->data, 255, session->write_impl.decoded_bytes_per_packet - write_frame->datalen); write_frame->datalen = session->write_impl.decoded_bytes_per_packet; } enc_frame = write_frame; session->enc_write_frame.datalen = session->enc_write_frame.buflen; status = switch_core_codec_encode(session->write_codec, frame->codec, enc_frame->data, enc_frame->datalen, session->write_impl.actual_samples_per_second, session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag); switch (status) { case SWITCH_STATUS_RESAMPLE: resample++; /* switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 2\n"); */ case SWITCH_STATUS_SUCCESS: session->enc_write_frame.codec = session->write_codec; session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t); if (frame->codec->implementation->samples_per_packet != session->write_impl.samples_per_packet) { session->enc_write_frame.timestamp = 0; } else { session->enc_write_frame.timestamp = frame->timestamp; } session->enc_write_frame.payload = session->write_impl.ianacode; session->enc_write_frame.m = frame->m; session->enc_write_frame.ssrc = frame->ssrc; session->enc_write_frame.seq = frame->seq; write_frame = &session->enc_write_frame; break; case SWITCH_STATUS_NOOP: enc_frame->codec = session->write_codec; enc_frame->samples = enc_frame->datalen / sizeof(int16_t); enc_frame->timestamp = frame->timestamp; enc_frame->m = frame->m; enc_frame->seq = frame->seq; enc_frame->ssrc = frame->ssrc; enc_frame->payload = enc_frame->codec->implementation->ianacode; write_frame = enc_frame; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_NOT_INITALIZED: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n"); write_frame = NULL; goto error; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error!\n", session->read_codec->codec_interface->interface_name); write_frame = NULL; goto error; } if (flag & SFF_CNG) { switch_set_flag(write_frame, SFF_CNG); } status = perform_write(session, write_frame, flags, stream_id); goto error; } else { if (!session->raw_write_buffer) { switch_size_t bytes_per_packet = session->write_impl.decoded_bytes_per_packet; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Engaging Write Buffer at %u bytes to accommodate %u->%u\n", (uint32_t) bytes_per_packet, write_frame->datalen, session->write_impl.decoded_bytes_per_packet); if ((status = switch_buffer_create_dynamic(&session->raw_write_buffer, bytes_per_packet * SWITCH_BUFFER_BLOCK_FRAMES, bytes_per_packet * SWITCH_BUFFER_START_FRAMES, 0)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Write Buffer Failed!\n"); goto error; } } if (!(switch_buffer_write(session->raw_write_buffer, write_frame->data, write_frame->datalen))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Write Buffer %u bytes Failed!\n", write_frame->datalen); status = SWITCH_STATUS_MEMERR; goto error; } status = SWITCH_STATUS_SUCCESS; while (switch_buffer_inuse(session->raw_write_buffer) >= session->write_impl.decoded_bytes_per_packet) { int rate; if (switch_channel_down(session->channel) || !session->raw_write_buffer) { goto error; } if ((session->raw_write_frame.datalen = (uint32_t) switch_buffer_read(session->raw_write_buffer, session->raw_write_frame.data, session->write_impl.decoded_bytes_per_packet)) == 0) { goto error; } enc_frame = &session->raw_write_frame; session->raw_write_frame.rate = session->write_impl.actual_samples_per_second; session->enc_write_frame.datalen = session->enc_write_frame.buflen; session->enc_write_frame.timestamp = 0; if (frame->codec && frame->codec->implementation && switch_core_codec_ready(frame->codec)) { rate = frame->codec->implementation->actual_samples_per_second; } else { rate = session->write_impl.actual_samples_per_second; } status = switch_core_codec_encode(session->write_codec, frame->codec, enc_frame->data, enc_frame->datalen, rate, session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag); switch (status) { case SWITCH_STATUS_RESAMPLE: resample++; session->enc_write_frame.codec = session->write_codec; session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t); session->enc_write_frame.m = frame->m; session->enc_write_frame.ssrc = frame->ssrc; session->enc_write_frame.payload = session->write_impl.ianacode; write_frame = &session->enc_write_frame; if (!session->write_resampler) { switch_mutex_lock(session->resample_mutex); if (!session->write_resampler) { status = switch_resample_create(&session->write_resampler, frame->codec->implementation->actual_samples_per_second, session->write_impl.actual_samples_per_second, session->write_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1); } switch_mutex_unlock(session->resample_mutex); if (status != SWITCH_STATUS_SUCCESS) { goto done; } } break; case SWITCH_STATUS_SUCCESS: session->enc_write_frame.codec = session->write_codec; session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t); session->enc_write_frame.m = frame->m; session->enc_write_frame.ssrc = frame->ssrc; session->enc_write_frame.payload = session->write_impl.ianacode; write_frame = &session->enc_write_frame; break; case SWITCH_STATUS_NOOP: if (session->write_resampler) { switch_mutex_lock(session->resample_mutex); if (session->write_resampler) { switch_resample_destroy(&session->write_resampler); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n"); } switch_mutex_unlock(session->resample_mutex); } enc_frame->codec = session->write_codec; enc_frame->samples = enc_frame->datalen / sizeof(int16_t); enc_frame->m = frame->m; enc_frame->ssrc = frame->ssrc; enc_frame->payload = enc_frame->codec->implementation->ianacode; write_frame = enc_frame; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_NOT_INITALIZED: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n"); write_frame = NULL; goto error; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error %d!\n", session->read_codec->codec_interface->interface_name, status); write_frame = NULL; goto error; } if (!did_write_resample && session->read_resampler) { short *data = write_frame->data; switch_mutex_lock(session->resample_mutex); if (session->read_resampler) { switch_resample_process(session->read_resampler, data, write_frame->datalen / 2); memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2); write_frame->samples = session->read_resampler->to_len; write_frame->datalen = session->read_resampler->to_len * 2; write_frame->rate = session->read_resampler->to_rate; } switch_mutex_unlock(session->resample_mutex); } if (flag & SFF_CNG) { switch_set_flag(write_frame, SFF_CNG); } if (ptime_mismatch || resample) { write_frame->timestamp = 0; } if ((status = perform_write(session, write_frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) { break; } } goto error; } } done: if (ptime_mismatch || resample) { write_frame->timestamp = 0; } if (do_write) { status = perform_write(session, write_frame, flags, stream_id); } error: switch_mutex_unlock(session->write_codec->mutex); switch_mutex_unlock(frame->codec->mutex); switch_mutex_unlock(session->codec_write_mutex); return status; }
SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) { switch_io_event_hook_read_frame_t *ptr; switch_status_t status = SWITCH_STATUS_FALSE; int need_codec, perfect, do_bugs = 0, do_resample = 0, is_cng = 0; switch_codec_implementation_t codec_impl; unsigned int flag = 0; switch_assert(session != NULL); if (switch_mutex_trylock(session->codec_read_mutex) == SWITCH_STATUS_SUCCESS) { switch_mutex_unlock(session->codec_read_mutex); } else { switch_cond_next(); *frame = &runtime.dummy_cng_frame; return SWITCH_STATUS_SUCCESS; } if (!(session->read_codec && session->read_codec->implementation && switch_core_codec_ready(session->read_codec))) { if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || switch_channel_get_state(session->channel) == CS_HIBERNATE) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s reading on a session with no media!\n", switch_channel_get_name(session->channel)); switch_cond_next(); *frame = &runtime.dummy_cng_frame; return SWITCH_STATUS_SUCCESS; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->codec_read_mutex); if (!switch_core_codec_ready(session->read_codec)) { switch_mutex_unlock(session->codec_read_mutex); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); *frame = &runtime.dummy_cng_frame; return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->read_codec->mutex); top: if (session->dmachine && !switch_channel_test_flag(session->channel, CF_BROADCAST)) { switch_ivr_dmachine_ping(session->dmachine, NULL); } if (switch_channel_down(session->channel) || !switch_core_codec_ready(session->read_codec)) { *frame = NULL; status = SWITCH_STATUS_FALSE; goto even_more_done; } status = SWITCH_STATUS_FALSE; need_codec = perfect = 0; *frame = NULL; if (session->read_codec && !session->track_id && session->track_duration) { if (session->read_frame_count == 0) { switch_event_t *event; session->read_frame_count = (session->read_impl.actual_samples_per_second / session->read_impl.samples_per_packet) * session->track_duration; switch_event_create(&event, SWITCH_EVENT_SESSION_HEARTBEAT); switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } else { session->read_frame_count--; } } if (switch_channel_test_flag(session->channel, CF_HOLD)) { switch_yield(session->read_impl.microseconds_per_packet); status = SWITCH_STATUS_BREAK; goto even_more_done; } if (session->endpoint_interface->io_routines->read_frame) { switch_mutex_unlock(session->read_codec->mutex); switch_mutex_unlock(session->codec_read_mutex); if ((status = session->endpoint_interface->io_routines->read_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) { for (ptr = session->event_hooks.read_frame; ptr; ptr = ptr->next) { if ((status = ptr->read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) { break; } } } if (!SWITCH_READ_ACCEPTABLE(status) || !session->read_codec || !switch_core_codec_ready(session->read_codec)) { *frame = NULL; return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->codec_read_mutex); if (!switch_core_codec_ready(session->read_codec)) { switch_mutex_unlock(session->codec_read_mutex); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); *frame = &runtime.dummy_cng_frame; return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->read_codec->mutex); if (!switch_core_codec_ready(session->read_codec)) { *frame = NULL; status = SWITCH_STATUS_FALSE; goto even_more_done; } } if (status != SWITCH_STATUS_SUCCESS) { goto done; } if (!(*frame)) { goto done; } switch_assert(*frame != NULL); if (switch_test_flag(*frame, SFF_PROXY_PACKET)) { /* Fast PASS! */ status = SWITCH_STATUS_SUCCESS; goto done; } if (switch_test_flag(*frame, SFF_CNG)) { status = SWITCH_STATUS_SUCCESS; if (!session->bugs && !session->plc) { goto done; } is_cng = 1; } switch_assert((*frame)->codec != NULL); if (!(session->read_codec && (*frame)->codec && (*frame)->codec->implementation) && switch_core_codec_ready((*frame)->codec)) { status = SWITCH_STATUS_FALSE; goto done; } codec_impl = *(*frame)->codec->implementation; if (session->read_codec->implementation->impl_id != codec_impl.impl_id) { need_codec = TRUE; } if (codec_impl.actual_samples_per_second != session->read_impl.actual_samples_per_second) { do_resample = 1; } if (session->bugs && !need_codec) { do_bugs = 1; need_codec = 1; } if (switch_test_flag(session, SSF_READ_TRANSCODE) && !need_codec && switch_core_codec_ready(session->read_codec)) { switch_core_session_t *other_session; const char *uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_SIGNAL_BOND_VARIABLE); switch_clear_flag(session, SSF_READ_TRANSCODE); if (uuid && (other_session = switch_core_session_locate(uuid))) { switch_set_flag(other_session, SSF_READ_CODEC_RESET); switch_set_flag(other_session, SSF_READ_CODEC_RESET); switch_set_flag(other_session, SSF_WRITE_CODEC_RESET); switch_core_session_rwunlock(other_session); } } if (switch_test_flag(session, SSF_READ_CODEC_RESET)) { switch_core_codec_reset(session->read_codec); switch_clear_flag(session, SSF_READ_CODEC_RESET); } if (status == SWITCH_STATUS_SUCCESS && need_codec) { switch_frame_t *enc_frame, *read_frame = *frame; switch_set_flag(session, SSF_READ_TRANSCODE); if (!switch_test_flag(session, SSF_WARN_TRANSCODE)) { switch_core_session_message_t msg = { 0 }; msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY; switch_core_session_receive_message(session, &msg); switch_set_flag(session, SSF_WARN_TRANSCODE); } if (read_frame->codec || is_cng) { session->raw_read_frame.datalen = session->raw_read_frame.buflen; if (is_cng) { if (session->plc) { plc_fillin(session->plc, session->raw_read_frame.data, read_frame->codec->implementation->decoded_bytes_per_packet / 2); is_cng = 0; flag &= !SFF_CNG; } else { memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet); } session->raw_read_frame.timestamp = 0; session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); read_frame = &session->raw_read_frame; status = SWITCH_STATUS_SUCCESS; } else { switch_codec_t *use_codec = read_frame->codec; if (do_bugs) { switch_thread_rwlock_wrlock(session->bug_rwlock); if (!session->bugs) { do_bugs = 0; switch_thread_rwlock_unlock(session->bug_rwlock); goto done; } if (!switch_core_codec_ready(&session->bug_codec)) { switch_core_codec_copy(read_frame->codec, &session->bug_codec, NULL); } use_codec = &session->bug_codec; switch_thread_rwlock_unlock(session->bug_rwlock); switch_thread_rwlock_wrlock(session->bug_rwlock); if (!session->bugs) { do_bugs = 0; } switch_thread_rwlock_unlock(session->bug_rwlock); if (!do_bugs) goto done; } if (switch_test_flag(read_frame, SFF_PLC)) { session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); memset(session->raw_read_frame.data, 255, session->raw_read_frame.datalen); status = SWITCH_STATUS_SUCCESS; } else { switch_thread_rwlock_rdlock(session->bug_rwlock); status = switch_core_codec_decode(use_codec->implementation?use_codec:read_frame->codec, session->read_codec, read_frame->data, read_frame->datalen, session->read_impl.actual_samples_per_second, session->raw_read_frame.data, &session->raw_read_frame.datalen, &session->raw_read_frame.rate, &read_frame->flags); switch_thread_rwlock_unlock(session->bug_rwlock); } if (status == SWITCH_STATUS_SUCCESS) { if ((switch_channel_test_flag(session->channel, CF_JITTERBUFFER) || switch_channel_test_flag(session->channel, CF_CNG_PLC)) && !session->plc) { session->plc = plc_init(NULL); } if (session->plc) { if (switch_test_flag(read_frame, SFF_PLC)) { plc_fillin(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2); switch_clear_flag(read_frame, SFF_PLC); } else { plc_rx(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2); } } } } if (do_resample && ((status == SWITCH_STATUS_SUCCESS) || is_cng)) { status = SWITCH_STATUS_RESAMPLE; } switch (status) { case SWITCH_STATUS_RESAMPLE: if (!session->read_resampler) { switch_mutex_lock(session->resample_mutex); status = switch_resample_create(&session->read_resampler, read_frame->codec->implementation->actual_samples_per_second, session->read_impl.actual_samples_per_second, session->read_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1); switch_mutex_unlock(session->resample_mutex); if (status != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to allocate resampler\n"); status = SWITCH_STATUS_FALSE; goto done; } } case SWITCH_STATUS_SUCCESS: session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); session->raw_read_frame.rate = read_frame->rate; if (read_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) { session->raw_read_frame.timestamp = 0; } else { session->raw_read_frame.timestamp = read_frame->timestamp; } session->raw_read_frame.ssrc = read_frame->ssrc; session->raw_read_frame.seq = read_frame->seq; session->raw_read_frame.m = read_frame->m; session->raw_read_frame.payload = read_frame->payload; session->raw_read_frame.flags = 0; if (switch_test_flag(read_frame, SFF_PLC)) { session->raw_read_frame.flags |= SFF_PLC; } read_frame = &session->raw_read_frame; break; case SWITCH_STATUS_NOOP: if (session->read_resampler) { switch_mutex_lock(session->resample_mutex); switch_resample_destroy(&session->read_resampler); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating read resampler\n"); switch_mutex_unlock(session->resample_mutex); } status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_BREAK: memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet); session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); session->raw_read_frame.timestamp = read_frame->timestamp; session->raw_read_frame.rate = read_frame->rate; session->raw_read_frame.ssrc = read_frame->ssrc; session->raw_read_frame.seq = read_frame->seq; session->raw_read_frame.m = read_frame->m; session->raw_read_frame.payload = read_frame->payload; session->raw_read_frame.flags = 0; if (switch_test_flag(read_frame, SFF_PLC)) { session->raw_read_frame.flags |= SFF_PLC; } read_frame = &session->raw_read_frame; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_NOT_INITALIZED: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n"); goto done; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error!\n", session->read_codec->codec_interface->interface_name); goto done; } } if (session->bugs) { switch_media_bug_t *bp; switch_bool_t ok = SWITCH_TRUE; int prune = 0; switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) { continue; } if (switch_test_flag(bp, SMBF_PRUNE)) { prune++; continue; } if (bp->ready && switch_test_flag(bp, SMBF_READ_STREAM)) { switch_mutex_lock(bp->read_mutex); switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen); if (bp->callback) { ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ); } switch_mutex_unlock(bp->read_mutex); } if (ok && switch_test_flag(bp, SMBF_READ_REPLACE)) { do_bugs = 0; if (bp->callback) { bp->read_replace_frame_in = read_frame; bp->read_replace_frame_out = read_frame; if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_REPLACE)) == SWITCH_TRUE) { read_frame = bp->read_replace_frame_out; } } } if ((bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) || ok == SWITCH_FALSE) { switch_set_flag(bp, SMBF_PRUNE); prune++; } } switch_thread_rwlock_unlock(session->bug_rwlock); if (prune) { switch_core_media_bug_prune(session); } } if (do_bugs) { goto done; } if (session->read_codec) { if (session->read_resampler) { short *data = read_frame->data; switch_mutex_lock(session->resample_mutex); switch_resample_process(session->read_resampler, data, (int) read_frame->datalen / 2); memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2); read_frame->samples = session->read_resampler->to_len; read_frame->datalen = session->read_resampler->to_len * 2; read_frame->rate = session->read_resampler->to_rate; switch_mutex_unlock(session->resample_mutex); } if (read_frame->datalen == session->read_impl.decoded_bytes_per_packet) { perfect = TRUE; } else { if (!session->raw_read_buffer) { switch_size_t bytes = session->read_impl.decoded_bytes_per_packet; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Engaging Read Buffer at %u bytes vs %u\n", (uint32_t) bytes, (uint32_t) (*frame)->datalen); switch_buffer_create_dynamic(&session->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, 0); } if (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen)) { status = SWITCH_STATUS_MEMERR; goto done; } } if (perfect || switch_buffer_inuse(session->raw_read_buffer) >= session->read_impl.decoded_bytes_per_packet) { if (perfect) { enc_frame = read_frame; session->raw_read_frame.rate = read_frame->rate; } else { session->raw_read_frame.datalen = (uint32_t) switch_buffer_read(session->raw_read_buffer, session->raw_read_frame.data, session->read_impl.decoded_bytes_per_packet); session->raw_read_frame.rate = session->read_impl.actual_samples_per_second; enc_frame = &session->raw_read_frame; } session->enc_read_frame.datalen = session->enc_read_frame.buflen; switch_assert(session->read_codec != NULL); switch_assert(enc_frame != NULL); switch_assert(enc_frame->data != NULL); status = switch_core_codec_encode(session->read_codec, enc_frame->codec, enc_frame->data, enc_frame->datalen, session->read_impl.actual_samples_per_second, session->enc_read_frame.data, &session->enc_read_frame.datalen, &session->enc_read_frame.rate, &flag); switch (status) { case SWITCH_STATUS_RESAMPLE: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 1\n"); case SWITCH_STATUS_SUCCESS: session->enc_read_frame.samples = session->read_impl.decoded_bytes_per_packet / sizeof(int16_t); if (perfect) { if (enc_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) { session->enc_read_frame.timestamp = 0; } else { session->enc_read_frame.timestamp = read_frame->timestamp; } session->enc_read_frame.rate = read_frame->rate; session->enc_read_frame.ssrc = read_frame->ssrc; session->enc_read_frame.seq = read_frame->seq; session->enc_read_frame.m = read_frame->m; session->enc_read_frame.payload = session->read_impl.ianacode; } *frame = &session->enc_read_frame; break; case SWITCH_STATUS_NOOP: session->raw_read_frame.samples = enc_frame->codec->implementation->samples_per_packet; session->raw_read_frame.timestamp = read_frame->timestamp; session->raw_read_frame.payload = enc_frame->codec->implementation->ianacode; session->raw_read_frame.m = read_frame->m; session->raw_read_frame.ssrc = read_frame->ssrc; session->raw_read_frame.seq = read_frame->seq; *frame = enc_frame; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_NOT_INITALIZED: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n"); *frame = NULL; status = SWITCH_STATUS_GENERR; break; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error!\n", session->read_codec->codec_interface->interface_name); *frame = NULL; status = SWITCH_STATUS_GENERR; break; } } else { goto top; } } } done: if (!(*frame)) { status = SWITCH_STATUS_FALSE; } else { if (flag & SFF_CNG) { switch_set_flag((*frame), SFF_CNG); } if (session->bugs) { switch_media_bug_t *bp; switch_bool_t ok = SWITCH_TRUE; int prune = 0; switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) { continue; } if (switch_test_flag(bp, SMBF_PRUNE)) { prune++; continue; } if (bp->ready && switch_test_flag(bp, SMBF_READ_PING)) { switch_mutex_lock(bp->read_mutex); if (bp->callback) { if (bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_PING) == SWITCH_FALSE || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) { ok = SWITCH_FALSE; } } switch_mutex_unlock(bp->read_mutex); } if (ok == SWITCH_FALSE) { switch_set_flag(bp, SMBF_PRUNE); prune++; } } switch_thread_rwlock_unlock(session->bug_rwlock); if (prune) { switch_core_media_bug_prune(session); } } } even_more_done: if (!*frame || !(*frame)->codec || !(*frame)->codec->implementation || !switch_core_codec_ready((*frame)->codec)) { *frame = &runtime.dummy_cng_frame; } switch_mutex_unlock(session->read_codec->mutex); switch_mutex_unlock(session->codec_read_mutex); return status; }
static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) { #ifdef AMR_PASSTHROUGH codec->flags |= SWITCH_CODEC_FLAG_PASSTHROUGH; if (codec->fmtp_in) { codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in); } return SWITCH_STATUS_SUCCESS; #else struct amr_context *context = NULL; switch_codec_fmtp_t codec_fmtp; amr_codec_settings_t amr_codec_settings; int encoding, decoding; int x, i, argc; char *argv[10]; char fmtptmp[128]; encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); decoding = (flags & SWITCH_CODEC_FLAG_DECODE); if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(struct amr_context))))) { return SWITCH_STATUS_FALSE; } else { memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp)); codec_fmtp.private_info = &amr_codec_settings; switch_amr_fmtp_parse(codec->fmtp_in, &codec_fmtp); if (context->enc_modes) { for (i = 7; i > -1; i++) { if (context->enc_modes & (1 << i)) { context->enc_mode = (switch_byte_t) i; break; } } } if (!context->enc_mode) { context->enc_mode = globals.default_bitrate; } switch_snprintf(fmtptmp, sizeof(fmtptmp), "octet-align=%d; mode-set=%d", switch_test_flag(context, AMR_OPT_OCTET_ALIGN) ? 1 : 0, context->enc_mode); codec->fmtp_out = switch_core_strdup(codec->memory_pool, fmtptmp); context->enc_mode = AMR_DEFAULT_BITRATE; context->encoder_state = NULL; context->decoder_state = NULL; if (encoding) { context->encoder_state = Encoder_Interface_init(context->dtx_mode); } if (decoding) { context->decoder_state = Decoder_Interface_init(); } codec->private_info = context; return SWITCH_STATUS_SUCCESS; } #endif }
static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) { #ifdef AMRWB_PASSTHROUGH codec->flags |= SWITCH_CODEC_FLAG_PASSTHROUGH; if (codec->fmtp_in) { codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in); } return SWITCH_STATUS_SUCCESS; #else struct amrwb_context *context = NULL; int encoding, decoding; int x, i, argc; char *argv[10]; char fmtptmp[128]; encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); decoding = (flags & SWITCH_CODEC_FLAG_DECODE); if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(struct amrwb_context))))) { return SWITCH_STATUS_FALSE; } else { if (codec->fmtp_in) { argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0]))); for (x = 0; x < argc; x++) { char *data = argv[x]; char *arg; while (*data && *data == ' ') { data++; } if ((arg = strchr(data, '='))) { *arg++ = '\0'; if (!strcasecmp(data, "octet-align")) { if (atoi(arg)) { switch_set_flag(context, AMRWB_OPT_OCTET_ALIGN); } } else if (!strcasecmp(data, "mode-change-neighbor")) { if (atoi(arg)) { switch_set_flag(context, AMRWB_OPT_MODE_CHANGE_NEIGHBOR); } } else if (!strcasecmp(data, "crc")) { if (atoi(arg)) { switch_set_flag(context, AMRWB_OPT_CRC); } } else if (!strcasecmp(data, "robust-sorting")) { if (atoi(arg)) { switch_set_flag(context, AMRWB_OPT_ROBUST_SORTING); } } else if (!strcasecmp(data, "interveaving")) { if (atoi(arg)) { switch_set_flag(context, AMRWB_OPT_INTERLEAVING); } } else if (!strcasecmp(data, "mode-change-period")) { context->change_period = atoi(arg); } else if (!strcasecmp(data, "ptime")) { context->ptime = (switch_byte_t) atoi(arg); } else if (!strcasecmp(data, "channels")) { context->channels = (switch_byte_t) atoi(arg); } else if (!strcasecmp(data, "maxptime")) { context->max_ptime = (switch_byte_t) atoi(arg); } else if (!strcasecmp(data, "mode-set")) { int y, m_argc; char *m_argv[8]; m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0]))); for (y = 0; y < m_argc; y++) { context->enc_modes |= (1 << atoi(m_argv[y])); } } } } } if (context->enc_modes) { for (i = 8; i > -1; i++) { if (context->enc_modes & (1 << i)) { context->enc_mode = (switch_byte_t) i; break; } } } if (!context->enc_mode) { context->enc_mode = globals.default_bitrate; } switch_snprintf(fmtptmp, sizeof(fmtptmp), "octet-align=%d; mode-set=%d", switch_test_flag(context, AMRWB_OPT_OCTET_ALIGN) ? 1 : 0, context->enc_mode); codec->fmtp_out = switch_core_strdup(codec->memory_pool, fmtptmp); context->enc_mode = AMRWB_DEFAULT_BITRATE; context->encoder_state = NULL; context->decoder_state = NULL; if (encoding) { context->encoder_state = E_IF_init(); } if (decoding) { context->decoder_state = D_IF_init(); } codec->private_info = context; return SWITCH_STATUS_SUCCESS; } #endif }
/*! function to load a grammar to the asr interface */ static switch_status_t pocketsphinx_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *name) { char *jsgf, *dic, *model, *rate = NULL; pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info; switch_status_t status = SWITCH_STATUS_FALSE; if (switch_test_flag(ps, PSFLAG_READY)) { ps_end_utt(ps->ps); switch_clear_flag(ps, PSFLAG_READY); } if (switch_is_file_path(grammar)) { jsgf = switch_mprintf("%s.gram", grammar); } else { jsgf = switch_mprintf("%s%s%s.gram", SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_PATH_SEPARATOR, grammar); } if (ah->rate == 8000) { model = switch_mprintf("%s%smodel%s%s", SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_PATH_SEPARATOR, SWITCH_PATH_SEPARATOR, globals.model8k); } else { model = switch_mprintf("%s%smodel%s%s", SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_PATH_SEPARATOR, SWITCH_PATH_SEPARATOR, globals.model16k); } dic = switch_mprintf("%s%s%s", SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_PATH_SEPARATOR, globals.dictionary); if (switch_file_exists(dic, ah->memory_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open dictionary %s.\n", dic); goto end; } if (switch_file_exists(model, ah->memory_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't open speech model %s.\n", model); goto end; } if (switch_file_exists(jsgf, ah->memory_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't open grammar file %s.\n", jsgf); goto end; } rate = switch_mprintf("%d", ah->rate); switch_assert(jsgf && dic && model); ps->config = cmd_ln_init(ps->config, ps_args(), FALSE, "-samprate", rate, "-hmm", model, "-jsgf", jsgf, "-lw", globals.language_weight, "-dict", dic, "-frate", "50", "-silprob", "0.005", NULL); if (ps->config == NULL) { status = SWITCH_STATUS_GENERR; goto end; } switch_mutex_lock(ps->flag_mutex); if (switch_test_flag(ps, PSFLAG_ALLOCATED)) { ps_reinit(ps->ps, ps->config); } else { if (!(ps->ps = ps_init(ps->config))) { switch_mutex_unlock(ps->flag_mutex); goto end; } switch_set_flag(ps, PSFLAG_ALLOCATED); } switch_mutex_unlock(ps->flag_mutex); ps_start_utt(ps->ps, NULL); switch_set_flag(ps, PSFLAG_READY); switch_safe_free(ps->grammar); ps->grammar = strdup(grammar); status = SWITCH_STATUS_SUCCESS; end: switch_safe_free(rate); switch_safe_free(jsgf); switch_safe_free(dic); switch_safe_free(model); return status; }
/** * open next file for reading * @param handle the file handle */ static switch_status_t next_file(switch_file_handle_t *handle) { struct rayo_file_context *context = handle->private_info; struct output_component *output = context->component ? OUTPUT_COMPONENT(context->component) : NULL; top: if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) { switch_core_file_close(&context->fh); } if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) { /* unsupported */ return SWITCH_STATUS_FALSE; } if (!context->cur_doc) { context->cur_doc = iks_find(output->document, "document"); if (!context->cur_doc) { iks_delete(output->document); output->document = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing <document>\n"); return SWITCH_STATUS_FALSE; } } else { context->cur_doc = iks_next_tag(context->cur_doc); } /* done? */ if (!context->cur_doc) { if (output->repeat_times == 0 || ++context->play_count < output->repeat_times) { /* repeat all document(s) */ if (!output->repeat_interval) { goto top; } } else { /* no more files to play */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Done playing\n"); return SWITCH_STATUS_FALSE; } } if (!context->cur_doc) { /* play silence between repeats */ switch_safe_free(context->ssml); context->ssml = switch_mprintf("silence_stream://%i", output->repeat_interval); } else { /* play next document */ iks *speak = NULL; switch_safe_free(context->ssml); context->ssml = NULL; speak = iks_find(context->cur_doc, "speak"); if (speak) { /* <speak> is child node */ char *ssml_str = iks_string(NULL, speak); if (zstr(output->renderer)) { /* FS must parse the SSML */ context->ssml = switch_mprintf("ssml://%s", ssml_str); } else { /* renderer will parse the SSML */ context->ssml = switch_mprintf("tts://%s||%s", output->renderer, ssml_str); } iks_free(ssml_str); } else if (iks_has_children(context->cur_doc)) { /* check if <speak> is in CDATA */ const char *ssml_str = NULL; iks *ssml = iks_child(context->cur_doc); if (ssml && iks_type(ssml) == IKS_CDATA) { ssml_str = iks_cdata(ssml); } if (zstr(ssml_str)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing <document> CDATA\n"); return SWITCH_STATUS_FALSE; } if (zstr(output->renderer)) { /* FS must parse the SSML */ context->ssml = switch_mprintf("ssml://%s", ssml_str); } else { /* renderer will parse the SSML */ context->ssml = switch_mprintf("tts://%s||%s", output->renderer, ssml_str); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing <speak>\n"); return SWITCH_STATUS_FALSE; } } if (switch_core_file_open(&context->fh, context->ssml, handle->channels, handle->samplerate, handle->flags, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Failed to open %s\n", context->ssml); goto top; } 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); } return SWITCH_STATUS_SUCCESS; }
/*! function to read results from the ASR*/ static switch_status_t pocketsphinx_asr_check_results(switch_asr_handle_t *ah, switch_asr_flag_t *flags) { pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info; return (switch_test_flag(ps, PSFLAG_HAS_TEXT) || switch_test_flag(ps, PSFLAG_BARGE)) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; }
/** * Read from file * @param handle * @param data * @param len * @return */ static switch_status_t fileman_file_read(switch_file_handle_t *handle, void *data, size_t *len) { struct fileman_file_context *context = (struct fileman_file_context *)handle->private_info; switch_file_handle_t *fh = &context->fh; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_size_t o_len = 0; /* anything called "_len" is measured in 2-byte samples */ if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) { return switch_core_file_read(fh, data, len); } //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "len = %"SWITCH_SIZE_T_FMT"\n", *len); if (*len > context->max_frame_len) { *len = context->max_frame_len; } for (;;) { int do_speed = 1; int last_speed = -1; size_t read_bytes = 0; if (switch_test_flag(handle, SWITCH_FILE_PAUSE)) { //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Read pause frame\n"); memset(context->abuf, 255, *len * 2); do_speed = 0; o_len = *len; } else if (fh->sp_audio_buffer && (context->eof || (switch_buffer_inuse(fh->sp_audio_buffer) > (switch_size_t) (*len * 2)))) { //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Read speed frame\n"); /* get next speed frame */ if (!(read_bytes = switch_buffer_read(fh->sp_audio_buffer, context->abuf, *len * 2))) { /* This is the reverse of what happens in switch_ivr_play_file... i think that implementation is wrong */ if (context->eof) { /* done with file */ status = SWITCH_STATUS_FALSE; goto done; } else { /* try again to fetch frame */ continue; } } /* pad short frame with silence */ if (read_bytes < *len * 2) { //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Padding speed frame %"SWITCH_SIZE_T_FMT" bytes\n", (context->frame_len * 2) - read_bytes); memset(context->abuf + read_bytes, 255, (*len * 2) - read_bytes); } o_len = *len; do_speed = 0; } else if (fh->audio_buffer && (context->eof || (switch_buffer_inuse(fh->audio_buffer) > (switch_size_t) (*len * 2)))) { //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "(2) Read audio frame\n"); /* get next file frame */ if (!(read_bytes = switch_buffer_read(fh->audio_buffer, context->abuf, *len * 2))) { if (context->eof) { /* done with file */ status = SWITCH_STATUS_FALSE; goto done; } else { /* try again to fetch frame */ continue; } } //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "(2) Read audio frame %"SWITCH_SIZE_T_FMT" bytes\n", read_bytes); fh->offset_pos += read_bytes / 2; //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "(2) file pos = %i\n", fh->offset_pos); /* pad short frame with silence */ if (read_bytes < (*len * 2)) { //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Padding audio frame %"SWITCH_SIZE_T_FMT" bytes\n", (context->frame_len * 2) - read_bytes); memset(context->abuf + read_bytes, 255, (*len * 2) - read_bytes); } o_len = *len; } else { if (context->eof) { /* done with file */ status = SWITCH_STATUS_FALSE; goto done; } o_len = FILE_STARTBYTES / 2; if (switch_core_file_read(fh, context->abuf, &o_len) != SWITCH_STATUS_SUCCESS) { context->eof++; /* at end of file... need to clear buffers before giving up */ continue; } //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Read file %"SWITCH_SIZE_T_FMT" bytes\n", o_len * 2); /* add file data to audio bufer */ read_bytes = switch_buffer_write(fh->audio_buffer, context->abuf, o_len * 2); //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Write audio frame %"SWITCH_SIZE_T_FMT" bytes\n", read_bytes); read_bytes = switch_buffer_read(fh->audio_buffer, context->abuf, *len * 2); o_len = read_bytes / 2; fh->offset_pos += o_len; //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Read audio frame %"SWITCH_SIZE_T_FMT" bytes\n", read_bytes); //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "file pos = %i\n", fh->offset_pos); } if (o_len <= 0) { //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "o_len <= 0 (%"SWITCH_SIZE_T_FMT")\n", o_len); status = SWITCH_STATUS_FALSE; goto done; } /* limit speed... there is a .25 factor change in packet size relative to original packet size for each increment. Too many increments and we cause badness when (factor * speed * o_len) > o_len */ if (handle->speed > 2) { handle->speed = 2; } else if (handle->speed < -2) { handle->speed = -2; } if (fh->audio_buffer && last_speed > -1 && last_speed != handle->speed) { /* speed has changed, flush the buffer */ switch_buffer_zero(fh->sp_audio_buffer); } if (switch_test_flag(fh, SWITCH_FILE_SEEK)) { /* file position has changed flush the buffer */ switch_buffer_zero(fh->audio_buffer); switch_clear_flag(fh, SWITCH_FILE_SEEK); } /* generate speed frames */ if (handle->speed && do_speed) { float factor = 0.25f * abs(handle->speed); switch_size_t new_len, supplement_len, step_len; short *bp = context->abuf; switch_size_t wrote_len = 0; //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Generate speed frame (%i)\n", handle->speed); supplement_len = (int) (factor * o_len); if (!supplement_len) { supplement_len = 1; } new_len = (handle->speed > 0) ? o_len - supplement_len : o_len + supplement_len; step_len = (handle->speed > 0) ? (new_len / supplement_len) : (o_len / supplement_len); if (!fh->sp_audio_buffer) { switch_buffer_create_dynamic(&fh->sp_audio_buffer, 1024, 1024, 0); } while ((wrote_len + step_len) < new_len) { switch_buffer_write(fh->sp_audio_buffer, bp, step_len * 2); wrote_len += step_len; bp += step_len; if (handle->speed > 0) { bp++; } else { float f; short s; f = (float) (*bp + *(bp + 1) + *(bp - 1)); f /= 3; s = (short) f; switch_buffer_write(fh->sp_audio_buffer, &s, 2); wrote_len++; } } if (wrote_len < new_len) { switch_size_t r_len = new_len - wrote_len; switch_buffer_write(fh->sp_audio_buffer, bp, r_len * 2); wrote_len += r_len; } last_speed = handle->speed; continue; } /* adjust volume on frame */ if (handle->vol) { //switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Adjust volume to = %i\n", handle->vol); switch_change_sln_volume(context->abuf, *len, handle->vol); } break; } done: /* copy frame over to return to caller */ memcpy(data, context->abuf, *len * 2); handle->offset_pos = context->fh.offset_pos; return status; }
static switch_status_t webm_file_write(switch_file_handle_t *handle, void *data, size_t *len) { uint32_t datalen = *len * 2 * handle->channels; switch_status_t status = SWITCH_STATUS_SUCCESS; uint8_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 }, *bp = buf; uint32_t encoded_rate; webm_file_context_t *context = (webm_file_context_t *)handle->private_info; uint32_t size = 0; if (!context->vid_ready) { return status; } context->audio_duration += *len; if (switch_test_flag(handle, SWITCH_FILE_NATIVE)) { size = datalen; memcpy(buf, data, datalen); } else { uint32_t rb; if (!context->audio_ready) { int offset = 1200; int fps = handle->samplerate / *len; int lead_frames = (offset * fps) / 1000; for (int x = 0; x < lead_frames; x++) { switch_buffer_write(context->audio_buffer, buf, datalen); } context->audio_ready = 1; } switch_buffer_write(context->audio_buffer, data, datalen); rb = switch_buffer_read(context->audio_buffer, data, datalen); datalen = rb; size = SWITCH_RECOMMENDED_BUFFER_SIZE; switch_core_codec_encode(&context->audio_codec, NULL, data, datalen, handle->samplerate, buf, &size, &encoded_rate, NULL); } if (size > 0) { // timecode still need to figure out for sync switch_mutex_lock(context->mutex); switch_core_timer_sync(&context->timer); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Writing audio %d bytes, ts: %lld\n", size, context->timer.samplecount); bool ret = context->segment->AddFrame(bp, size, context->audio_track_id, context->timer.samplecount * 1000LL, true); // bool ret = context->segment->AddFrame((const uint8_t *)buf, size, context->audio_track_id, context->audio_duration, true); switch_mutex_unlock(context->mutex); if (!ret) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing audio %d bytes, pts: %lld or %lld\n", size, context->timer.samplecount * 1000LL, context->audio_duration); } } return status; }
static switch_bool_t capture_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { switch_core_session_t *session = switch_core_media_bug_get_session(bug); switch_channel_t *channel = switch_core_session_get_channel(session); struct cap_cb *cb = (struct cap_cb *) user_data; switch (type) { case SWITCH_ABC_TYPE_INIT: break; case SWITCH_ABC_TYPE_CLOSE: { if (cb->buffer) { switch_buffer_destroy(&cb->buffer); } switch_channel_set_private(channel, "snapshot", NULL); } break; case SWITCH_ABC_TYPE_READ: if (cb->buffer) { uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE]; switch_frame_t frame = { 0 }; frame.data = data; frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; if (switch_mutex_trylock(cb->mutex) == SWITCH_STATUS_SUCCESS) { while (switch_core_media_bug_read(bug, &frame, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS && !switch_test_flag((&frame), SFF_CNG)) { if (frame.datalen) switch_buffer_slide_write(cb->buffer, frame.data, frame.datalen); } switch_mutex_unlock(cb->mutex); } } break; case SWITCH_ABC_TYPE_WRITE: default: break; } return SWITCH_TRUE; }
static switch_status_t webm_file_open(switch_file_handle_t *handle, const char *path) { webm_file_context_t *context; char *ext; unsigned int flags = 0; const char *tmp = NULL; char *fmtp; if ((ext = strrchr((char *)path, '.')) == 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Format\n"); return SWITCH_STATUS_GENERR; } ext++; if ((context = (webm_file_context_t *)switch_core_alloc(handle->memory_pool, sizeof(webm_file_context_t))) == 0) { return SWITCH_STATUS_MEMERR; } memset(context, 0, sizeof(webm_file_context_t)); context->offset = -100; if (handle->params && (tmp = switch_event_get_header(handle->params, "webmv2_video_offset"))) { context->offset = atoi(tmp); } switch_mutex_init(&context->mutex, SWITCH_MUTEX_NESTED, handle->memory_pool); switch_core_timer_init(&context->timer, "soft", 1, 1000, context->pool); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "init timer\n"); if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) { flags |= SWITCH_FOPEN_WRITE | SWITCH_FOPEN_CREATE; if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND) || switch_test_flag(handle, SWITCH_FILE_WRITE_OVER)) { flags |= SWITCH_FOPEN_READ; } else { flags |= SWITCH_FOPEN_TRUNCATE; } } if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) { flags |= SWITCH_FOPEN_READ; } context->writer = new mkvmuxer::MkvWriter(); if (!context->writer->Open(path)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error opening file %s\n", path); return SWITCH_STATUS_GENERR; } context->segment = new mkvmuxer::Segment(); if (!context->segment || !context->segment->Init(context->writer)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error init segment\n"); return SWITCH_STATUS_GENERR; } // context->segment.set_mode(mkvmuxer::Segment::kLive); context->segment->set_mode(mkvmuxer::Segment::kFile); context->segment->OutputCues(true); mkvmuxer::SegmentInfo* const info = context->segment->GetSegmentInfo(); info->set_timecode_scale(1000000); info->set_muxing_app("FreeSWITCH"); info->set_writing_app(switch_version_full()); context->audio_track_id = context->segment->AddAudioTrack(handle->samplerate, handle->channels, 0); if (!context->audio_track_id) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error add audio track!\n"); goto end; } context->audio = static_cast<mkvmuxer::AudioTrack*>(context->segment->GetTrackByNumber(context->audio_track_id)); context->audio->set_codec_id("A_" AUDIO_CODEC); switch_buffer_create_dynamic(&context->audio_buffer, 512, 512, 0); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sample rate: %d, channels: %d\n", handle->samplerate, handle->channels); handle->format = 0; handle->sections = 0; handle->seekable = 0; handle->speed = 0; handle->pos = 0; handle->private_info = context; context->pool = handle->memory_pool; // handle->flags |= SWITCH_FILE_NATIVE; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Opening File [%s] %dhz %s\n", path, handle->samplerate, switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO) ? " with VIDEO" : ""); fmtp = switch_core_sprintf(context->pool, "useinbandfec=1;minptime=20;ptime=20;samplerate=%d%s", handle->samplerate, handle->channels == 2 ? ",stereo=1" : ""); if (switch_core_codec_init(&context->audio_codec, AUDIO_CODEC, NULL, fmtp, handle->samplerate, 20,//ms handle->channels, SWITCH_CODEC_FLAG_ENCODE, NULL, handle->memory_pool) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Audio Codec Activation Success\n"); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Audio Codec Activation Fail\n"); goto end; } if (switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO)) { if (switch_core_codec_init(&context->video_codec, "VP8", NULL, NULL, 90000, 0,//ms 1, SWITCH_CODEC_FLAG_ENCODE, NULL, handle->memory_pool) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Video Codec H264 Activation Success\n"); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Video Codec H264 Activation Fail\n"); goto end; } } if (!strcmp(AUDIO_CODEC, "VORBIS")) { uint16_t size = 0; uint8_t *codec_private_data = NULL; switch_core_codec_control(&context->audio_codec, SCC_GET_CODEC_PRIVATE, SCCT_INT, (void *)&size, NULL, (void **)&codec_private_data); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "======codec_private_data size: %d data: %p\n", size, codec_private_data); context->audio->SetCodecPrivate(codec_private_data, size); } if (1) { // for better quality? int bw = 4096; switch_core_codec_control(&context->video_codec, SCC_VIDEO_BANDWIDTH, SCCT_INT, (void *)&bw, NULL, NULL); } switch_buffer_create_dynamic(&context->buf, 512, 512, 1024000); return SWITCH_STATUS_SUCCESS; end: if (context->segment) delete context->segment; if (context->writer) delete context->writer; return SWITCH_STATUS_GENERR; }
void do_broadcast(switch_stream_handle_t *stream) { char *path_info = switch_event_get_header(stream->param_event, "http-path-info"); char *file; lame_global_flags *gfp = NULL; switch_file_handle_t fh = { 0 }; unsigned char mp3buf[TC_BUFFER_SIZE] = ""; uint8_t buf[1024]; int rlen; int is_local = 0; uint32_t interval = 20000; if (strstr(path_info + 7, "://")) { file = strdup(path_info + 7); is_local++; } else { file = switch_mprintf("%s/streamfiles/%s", SWITCH_GLOBAL_dirs.base_dir, path_info + 7); } assert(file); if (switch_core_file_open(&fh, file, 0, 0, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { memset(&fh, 0, sizeof(fh)); stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>File not found</h2>\n"); goto end; } if (switch_test_flag((&fh), SWITCH_FILE_NATIVE)) { stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>File format not supported</h2>\n"); goto end; } if (!(gfp = lame_init())) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n"); goto end; } lame_set_num_channels(gfp, fh.channels); lame_set_in_samplerate(gfp, fh.samplerate); lame_set_brate(gfp, 16 * (fh.samplerate / 8000) * fh.channels); lame_set_mode(gfp, 3); lame_set_quality(gfp, 2); lame_set_errorf(gfp, log_error); lame_set_debugf(gfp, log_debug); lame_set_msgf(gfp, log_msg); lame_set_bWriteVbrTag(gfp, 0); lame_mp3_tags_fid(gfp, NULL); lame_init_params(gfp); lame_print_config(gfp); stream->write_function(stream, "Content-type: audio/mpeg\r\n" "Content-Disposition: inline; filename=\"%s.mp3\"\r\n\r\n", path_info + 7); if (fh.interval) { interval = fh.interval * 1000; } for (;;) { switch_size_t samples = sizeof(buf) / 2; switch_core_file_read(&fh, buf, &samples); if (is_local) { switch_yield(interval); } if (!samples) { break; } if ((rlen = lame_encode_buffer(gfp, (void *) buf, NULL, samples, mp3buf, sizeof(mp3buf))) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen); goto end; } if (rlen) { if (stream->raw_write_function(stream, mp3buf, rlen)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n"); goto end; } } } while ((rlen = lame_encode_flush(gfp, mp3buf, sizeof(mp3buf))) > 0) { if (stream->raw_write_function(stream, mp3buf, rlen)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n"); goto end; } } end: if (fh.channels) { switch_core_file_close(&fh); } switch_safe_free(file); if (gfp) { lame_close(gfp); gfp = NULL; } }
static JSBool teletone_generate(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval) { struct teletone_obj *tto = JS_GetPrivate(cx, obj); int32 loops = 0; if (argc > 0) { char *script; switch_core_session_t *session; switch_frame_t write_frame = { 0 }; unsigned char *fdata[1024]; switch_frame_t *read_frame; switch_channel_t *channel; if (argc > 1) { if (!JS_ValueToInt32(cx, argv[1], &loops)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Convert to INT\n"); return JS_FALSE; } loops--; } if (tto->audio_buffer) { switch_buffer_zero(tto->audio_buffer); } tto->ts.debug = 1; tto->ts.debug_stream = switch_core_get_console(); script = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); teletone_run(&tto->ts, script); session = tto->session; write_frame.codec = &tto->codec; write_frame.data = fdata; write_frame.buflen = sizeof(fdata); channel = switch_core_session_get_channel(session); if (tto->timer) { switch_core_service_session(session); } if (loops) { switch_buffer_set_loops(tto->audio_buffer, loops); } for (;;) { if (switch_test_flag(tto, TTF_DTMF)) { char dtmf[128]; char *ret; if (switch_channel_has_dtmf(channel)) { uintN aargc = 0; jsval aargv[4]; switch_channel_dequeue_dtmf_string(channel, dtmf, sizeof(dtmf)); aargv[aargc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, dtmf)); JS_CallFunction(cx, obj, tto->function, aargc, aargv, &tto->ret); ret = JS_GetStringBytes(JS_ValueToString(cx, tto->ret)); if (strcmp(ret, "true") && strcmp(ret, "undefined")) { *rval = tto->ret; return JS_TRUE; } } } if (tto->timer) { if (switch_core_timer_next(tto->timer) != SWITCH_STATUS_SUCCESS) { break; } } else { switch_status_t status; status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); if (!SWITCH_READ_ACCEPTABLE(status)) { break; } } if ((write_frame.datalen = (uint32_t) switch_buffer_read_loop(tto->audio_buffer, fdata, write_frame.codec->implementation->decoded_bytes_per_packet)) <= 0) { break; } write_frame.samples = write_frame.datalen / 2; if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad Write\n"); break; } } if (tto->timer) { switch_core_thread_session_end(session); } return JS_TRUE; } return JS_FALSE; }
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *bug, switch_frame_t *frame, switch_bool_t fill) { switch_size_t bytes = 0, datalen = 0; int16_t *dp, *fp; uint32_t x; size_t rlen = 0; size_t wlen = 0; uint32_t blen; switch_codec_implementation_t read_impl = { 0 }; int16_t *tp; switch_size_t do_read = 0, do_write = 0; int fill_read = 0, fill_write = 0; switch_core_session_get_read_impl(bug->session, &read_impl); bytes = read_impl.decoded_bytes_per_packet; if (frame->buflen < bytes) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "%s frame buffer too small!\n", switch_channel_get_name(bug->session->channel)); return SWITCH_STATUS_FALSE; } if ((!bug->raw_read_buffer && (!bug->raw_write_buffer || !switch_test_flag(bug, SMBF_WRITE_STREAM)))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "%s Buffer Error (raw_read_buffer=%p, raw_write_buffer=%p, read=%s, write=%s)\n", switch_channel_get_name(bug->session->channel), (void *)bug->raw_read_buffer, (void *)bug->raw_write_buffer, switch_test_flag(bug, SMBF_READ_STREAM) ? "yes" : "no", switch_test_flag(bug, SMBF_WRITE_STREAM) ? "yes" : "no"); return SWITCH_STATUS_FALSE; } frame->flags = 0; frame->datalen = 0; if (switch_test_flag(bug, SMBF_READ_STREAM)) { switch_mutex_lock(bug->read_mutex); do_read = switch_buffer_inuse(bug->raw_read_buffer); switch_mutex_unlock(bug->read_mutex); } if (switch_test_flag(bug, SMBF_WRITE_STREAM)) { switch_mutex_lock(bug->write_mutex); do_write = switch_buffer_inuse(bug->raw_write_buffer); switch_mutex_unlock(bug->write_mutex); } if (bug->record_frame_size && bug->record_pre_buffer_max && (do_read || do_write) && bug->record_pre_buffer_count < bug->record_pre_buffer_max) { bug->record_pre_buffer_count++; return SWITCH_STATUS_FALSE; } if (!bug->record_frame_size) { switch_size_t frame_size; switch_codec_implementation_t read_impl = { 0 }; //switch_codec_implementation_t other_read_impl = { 0 }; //switch_core_session_t *other_session; switch_core_session_get_read_impl(bug->session, &read_impl); frame_size = read_impl.decoded_bytes_per_packet; bug->record_frame_size = frame_size; #if 0 if (do_read && do_write) { if (switch_core_session_get_partner(bug->session, &other_session) == SWITCH_STATUS_SUCCESS) { switch_core_session_get_read_impl(other_session, &other_read_impl); switch_core_session_rwunlock(other_session); if (read_impl.actual_samples_per_second == other_read_impl.actual_samples_per_second) { if (read_impl.decoded_bytes_per_packet < other_read_impl.decoded_bytes_per_packet) { frame_size = read_impl.decoded_bytes_per_packet; } } else { if (read_impl.decoded_bytes_per_packet > other_read_impl.decoded_bytes_per_packet) { frame_size = read_impl.decoded_bytes_per_packet; } } } bug->record_frame_size = frame_size; } #endif } if (bug->record_frame_size) { if ((do_read && do_read < bug->record_frame_size) || (do_write && do_write < bug->record_frame_size)) { return SWITCH_STATUS_FALSE; } if (do_read && do_read > bug->record_frame_size) { do_read = bug->record_frame_size; } if (do_write && do_write > bug->record_frame_size) { do_write = bug->record_frame_size; } } fill_read = !do_read; fill_write = !do_write; if (fill_read && fill_write) { return SWITCH_STATUS_FALSE; } if (do_read && do_read > SWITCH_RECOMMENDED_BUFFER_SIZE) { do_read = 1280; } if (do_write && do_write > SWITCH_RECOMMENDED_BUFFER_SIZE) { do_write = 1280; } if (do_read) { switch_mutex_lock(bug->read_mutex); frame->datalen = (uint32_t) switch_buffer_read(bug->raw_read_buffer, frame->data, do_read); if (frame->datalen != do_read) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "Framing Error Reading!\n"); switch_core_media_bug_flush(bug); switch_mutex_unlock(bug->read_mutex); return SWITCH_STATUS_FALSE; } switch_mutex_unlock(bug->read_mutex); } else if (fill_read) { frame->datalen = bytes; memset(frame->data, 255, frame->datalen); } if (do_write) { switch_assert(bug->raw_write_buffer); switch_mutex_lock(bug->write_mutex); datalen = (uint32_t) switch_buffer_read(bug->raw_write_buffer, bug->data, do_write); if (datalen != do_write) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "Framing Error Writing!\n"); switch_core_media_bug_flush(bug); switch_mutex_unlock(bug->write_mutex); return SWITCH_STATUS_FALSE; } switch_mutex_unlock(bug->write_mutex); } else if (fill_write) { datalen = bytes; memset(bug->data, 255, datalen); } tp = bug->tmp; dp = (int16_t *) bug->data; fp = (int16_t *) frame->data; rlen = frame->datalen / 2; wlen = datalen / 2; blen = bytes / 2; if (switch_test_flag(bug, SMBF_STEREO)) { int16_t *left, *right; size_t left_len, right_len; if (switch_test_flag(bug, SMBF_STEREO_SWAP)) { left = dp; /* write stream */ left_len = wlen; right = fp; /* read stream */ right_len = rlen; } else { left = fp; /* read stream */ left_len = rlen; right = dp; /* write stream */ right_len = wlen; } for (x = 0; x < blen; x++) { if (x < left_len) { *(tp++) = *(left + x); } else { *(tp++) = 0; } if (x < right_len) { *(tp++) = *(right + x); } else { *(tp++) = 0; } } memcpy(frame->data, bug->tmp, bytes * 2); } else { for (x = 0; x < blen; x++) { int32_t w = 0, r = 0, z = 0; if (x < rlen) { r = (int32_t) * (fp + x); } if (x < wlen) { w = (int32_t) * (dp + x); } z = w + r; if (z > SWITCH_SMAX || z < SWITCH_SMIN) { if (r) z += (r/2); if (w) z += (w/2); } switch_normalize_to_16bit(z); *(fp + x) = (int16_t) z; } } frame->datalen = bytes; frame->samples = bytes / sizeof(int16_t); frame->rate = read_impl.actual_samples_per_second; frame->codec = NULL; if (fill_read && fill_write) { return SWITCH_STATUS_BREAK; } if (fill_read || fill_write) { return SWITCH_STATUS_BREAK; } memcpy(bug->session->recur_buffer, frame->data, frame->datalen); bug->session->recur_buffer_len = frame->datalen; return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_core_speech_read_tts(switch_speech_handle_t *sh, void *data, switch_size_t *datalen, switch_speech_flag_t *flags) { switch_status_t status; switch_size_t want, orig_len = *datalen; switch_assert(sh != NULL); want = *datalen; top: if (sh->buffer && (switch_buffer_inuse(sh->buffer) >= orig_len || switch_test_flag(sh, SWITCH_SPEECH_FLAG_DONE))) { if ((*datalen = switch_buffer_read(sh->buffer, data, orig_len))) { return SWITCH_STATUS_SUCCESS; } } if (switch_test_flag(sh, SWITCH_SPEECH_FLAG_DONE)) { switch_clear_flag(sh, SWITCH_SPEECH_FLAG_DONE); *datalen = 0; return SWITCH_STATUS_BREAK; } more: if ((status = sh->speech_interface->speech_read_tts(sh, data, datalen, flags)) != SWITCH_STATUS_SUCCESS) { switch_set_flag(sh, SWITCH_SPEECH_FLAG_DONE); goto top; } if (sh->native_rate && sh->samplerate && sh->native_rate != sh->samplerate) { if (!sh->resampler) { if (switch_resample_create(&sh->resampler, sh->native_rate, sh->samplerate, (uint32_t) orig_len, SWITCH_RESAMPLE_QUALITY, 1) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n"); return SWITCH_STATUS_GENERR; } } switch_resample_process(sh->resampler, data, *datalen / 2); if (sh->resampler->to_len < want / 2 || sh->resampler->to_len > orig_len / 2) { if (!sh->buffer) { int factor = sh->resampler->to_len * sh->samplerate / 1000; switch_buffer_create_dynamic(&sh->buffer, factor, factor, 0); switch_assert(sh->buffer); } if (!sh->dbuf || sh->dbuflen < sh->resampler->to_len * 2) { sh->dbuflen = sh->resampler->to_len * 2; sh->dbuf = switch_core_alloc(sh->memory_pool, sh->dbuflen); } switch_assert(sh->resampler->to_len <= sh->dbuflen); memcpy((int16_t *) sh->dbuf, sh->resampler->to, sh->resampler->to_len * 2); switch_buffer_write(sh->buffer, sh->dbuf, sh->resampler->to_len * 2); if (switch_buffer_inuse(sh->buffer) < want) { *datalen = want; goto more; } *datalen = switch_buffer_read(sh->buffer, data, orig_len); status = SWITCH_STATUS_SUCCESS; } else { memcpy(data, sh->resampler->to, sh->resampler->to_len * 2); *datalen = sh->resampler->to_len * 2; status = SWITCH_STATUS_SUCCESS; } } return status; }
SWITCH_DECLARE(uint32_t) switch_core_media_bug_test_flag(switch_media_bug_t *bug, uint32_t flag) { return switch_test_flag(bug, flag); }
SWITCH_DECLARE(switch_status_t) CoreSession::process_callback_result(char *result) { this_check(SWITCH_STATUS_FALSE); sanity_check(SWITCH_STATUS_FALSE); if (zstr(result)) { return SWITCH_STATUS_SUCCESS; } if (fhp) { if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { return SWITCH_STATUS_FALSE; } if (!strncasecmp(result, "speed", 5)) { char *p; if ((p = strchr(result, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { step = 1; } fhp->speed += step; } else { int speed = atoi(p); fhp->speed = speed; } return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; } else if (!strncasecmp(result, "volume", 6)) { char *p; if ((p = strchr(result, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { step = 1; } fhp->vol += step; } else { int vol = atoi(p); fhp->vol = vol; } return SWITCH_STATUS_SUCCESS; } if (fhp->vol) { switch_normalize_volume(fhp->vol); } return SWITCH_STATUS_FALSE; } else if (!strcasecmp(result, "pause")) { if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)) { switch_clear_flag(fhp, SWITCH_FILE_PAUSE); } else { switch_set_flag(fhp, SWITCH_FILE_PAUSE); } return SWITCH_STATUS_SUCCESS; } else if (!strcasecmp(result, "stop")) { return SWITCH_STATUS_FALSE; } else if (!strcasecmp(result, "truncate")) { switch_core_file_truncate(fhp, 0); } else if (!strcasecmp(result, "restart")) { unsigned int pos = 0; fhp->speed = 0; switch_core_file_seek(fhp, &pos, 0, SEEK_SET); return SWITCH_STATUS_SUCCESS; } else if (!strncasecmp(result, "seek", 4)) { switch_codec_t *codec; unsigned int samps = 0; unsigned int pos = 0; char *p; codec = switch_core_session_get_read_codec(session); if ((p = strchr(result, ':'))) { p++; if (*p == '+' || *p == '-') { int step; int32_t target; if (!(step = atoi(p))) { step = 1000; } samps = step * (codec->implementation->samples_per_second / 1000); target = (int32_t)fhp->pos + samps; if (target < 0) { target = 0; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target); switch_core_file_seek(fhp, &pos, target, SEEK_SET); } else { samps = atoi(p) * (codec->implementation->samples_per_second / 1000); if (samps < 0) { samps = 0; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps); switch_core_file_seek(fhp, &pos, samps, SEEK_SET); } } return SWITCH_STATUS_SUCCESS; } } if (!strcmp(result, "true") || !strcmp(result, "undefined")) { return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }
/* State methods they get called when the state changes to the specific state returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it. */ static switch_status_t channel_on_init(switch_core_session_t *session) { switch_channel_t *channel, *b_channel; loopback_private_t *tech_pvt = NULL, *b_tech_pvt = NULL; switch_core_session_t *b_session; char name[128]; switch_caller_profile_t *caller_profile; switch_event_t *vars = NULL; const char *var; tech_pvt = switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND) && !switch_test_flag(tech_pvt, TFLAG_BLEG)) { if (!(b_session = switch_core_session_request(loopback_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure.\n"); goto end; } if (switch_core_session_read_lock(b_session) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure.\n"); switch_core_session_destroy(&b_session); goto end; } switch_core_session_add_stream(b_session, NULL); b_channel = switch_core_session_get_channel(b_session); b_tech_pvt = (loopback_private_t *) switch_core_session_alloc(b_session, sizeof(*b_tech_pvt)); switch_snprintf(name, sizeof(name), "loopback/%s-b", tech_pvt->caller_profile->destination_number); switch_channel_set_name(b_channel, name); if (tech_init(b_tech_pvt, b_session, switch_core_session_get_read_codec(session)) != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_core_session_destroy(&b_session); goto end; } caller_profile = switch_caller_profile_clone(b_session, tech_pvt->caller_profile); caller_profile->source = switch_core_strdup(caller_profile->pool, modname); switch_channel_set_caller_profile(b_channel, caller_profile); b_tech_pvt->caller_profile = caller_profile; switch_channel_set_state(b_channel, CS_INIT); switch_mutex_lock(tech_pvt->mutex); tech_pvt->other_session = b_session; tech_pvt->other_tech_pvt = b_tech_pvt; tech_pvt->other_channel = b_channel; switch_mutex_unlock(tech_pvt->mutex); //b_tech_pvt->other_session = session; //b_tech_pvt->other_tech_pvt = tech_pvt; //b_tech_pvt->other_channel = channel; b_tech_pvt->other_uuid = switch_core_session_strdup(b_session, switch_core_session_get_uuid(session)); switch_set_flag_locked(tech_pvt, TFLAG_LINKED); switch_set_flag_locked(b_tech_pvt, TFLAG_LINKED); switch_set_flag_locked(b_tech_pvt, TFLAG_BLEG); switch_channel_set_flag(channel, CF_ACCEPT_CNG); if ((vars = (switch_event_t *) switch_channel_get_private(channel, "__loopback_vars__"))) { switch_event_header_t *h; switch_channel_set_private(channel, "__loopback_vars__", NULL); for (h = vars->headers; h; h = h->next) { switch_channel_set_variable(tech_pvt->other_channel, h->name, h->value); } switch_event_destroy(&vars); } if ((var = switch_channel_get_variable(channel, "loopback_export"))) { int argc = 0; char *argv[128] = { 0 }; char *dup = switch_core_session_strdup(session, var); if ((argc = switch_split(dup, ',', argv))) { int i; for (i = 0; i < argc; i++) { if (!zstr(argv[i])) { const char *val = switch_channel_get_variable(channel, argv[i]); if(!zstr(val)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Transfer variable [%s]=[%s] %s -> %s\n", argv[i], val, switch_channel_get_name(channel), switch_channel_get_name(tech_pvt->other_channel)); switch_channel_set_variable(tech_pvt->other_channel, argv[i], val); } } } } } if (switch_test_flag(tech_pvt, TFLAG_APP)) { switch_set_flag(b_tech_pvt, TFLAG_APP); switch_clear_flag(tech_pvt, TFLAG_APP); } switch_channel_set_variable(channel, "other_loopback_leg_uuid", switch_channel_get_uuid(b_channel)); switch_channel_set_variable(b_channel, "other_loopback_leg_uuid", switch_channel_get_uuid(channel)); if (switch_core_session_thread_launch(b_session) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error spawning thread\n"); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); goto end; } } else { switch_mutex_lock(tech_pvt->mutex); if ((tech_pvt->other_session = switch_core_session_locate(tech_pvt->other_uuid))) { tech_pvt->other_tech_pvt = switch_core_session_get_private(tech_pvt->other_session); tech_pvt->other_channel = switch_core_session_get_channel(tech_pvt->other_session); } switch_mutex_unlock(tech_pvt->mutex); } if (!tech_pvt->other_session) { switch_clear_flag_locked(tech_pvt, TFLAG_LINKED); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); goto end; } switch_channel_set_variable(channel, "loopback_leg", switch_test_flag(tech_pvt, TFLAG_BLEG) ? "B" : "A"); switch_channel_set_state(channel, CS_ROUTING); end: return SWITCH_STATUS_SUCCESS; }
/*! function to feed audio to the ASR */ static switch_status_t pocketsphinx_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags) { pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info; int rv = 0; int ret = MSP_SUCCESS; int errcode = MSP_SUCCESS; //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, ">>>>>>>>pocketsphinx_asr_feed<<<<<<<<<\n"); if (switch_test_flag(ah, SWITCH_ASR_FLAG_CLOSED)) return SWITCH_STATUS_BREAK; if (!switch_test_flag(ps, PSFLAG_NOMATCH) && !switch_test_flag(ps, PSFLAG_NOINPUT) && !switch_test_flag(ps, PSFLAG_HAS_TEXT) && switch_test_flag(ps, PSFLAG_READY)) { if (stop_detect(ps, (int16_t *) data, len / 2)) { char const *hyp; switch_mutex_lock(ps->flag_mutex); QISRAudioWrite(ps->ifly_session_id, NULL, 0, MSP_AUDIO_SAMPLE_LAST, &(ps->ifly_ep_stat), &(ps->ifly_rec_stat)); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, ">>>>>>>> tell zero <<<<<<<<<\n"); hyp = QISRGetResult(ps->ifly_session_id, &(ps->ifly_rec_stat), 0, &errcode); if (hyp || ps->ifly_rec_stat != MSP_REC_STATUS_INCOMPLETE) { ps->ifly_wait_result = SWITCH_FALSE; } if (hyp) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, ">>>>>>>> k0<<<<<<<<<\n"); if (errcode == MSP_SUCCESS && !zstr(hyp)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, ">>>>>>>> k2<<<<<<<<<\n"); switch_clear_flag(ps, PSFLAG_READY); ps->hyp = switch_core_strdup(ah->memory_pool, hyp); switch_set_flag(ps, PSFLAG_HAS_TEXT); } } if (switch_test_flag(ps, PSFLAG_SPEECH_TIMEOUT) && !switch_test_flag(ps, PSFLAG_HAS_TEXT)) { /* heard something, but doesn't match anything */ switch_clear_flag(ps, PSFLAG_READY); switch_set_flag(ps, PSFLAG_NOMATCH); } switch_mutex_unlock(ps->flag_mutex); } else if ( ps->ifly_wait_result == SWITCH_TRUE ) { char const *hyp; switch_mutex_lock(ps->flag_mutex); hyp = QISRGetResult(ps->ifly_session_id, &(ps->ifly_rec_stat), 0, &errcode); if (hyp || ps->ifly_rec_stat != MSP_REC_STATUS_INCOMPLETE) { ps->ifly_wait_result = SWITCH_FALSE; } if (hyp) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, ">>>>>>>> k0<<<<<<<<<\n"); if (errcode == MSP_SUCCESS && !zstr(hyp)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, ">>>>>>>> k2<<<<<<<<<\n"); switch_clear_flag(ps, PSFLAG_READY); ps->hyp = switch_core_strdup(ah->memory_pool, hyp); switch_set_flag(ps, PSFLAG_HAS_TEXT); } } switch_mutex_unlock(ps->flag_mutex); } /* only feed ps_process_raw when we are listening */ if (ps->listening) { switch_mutex_lock(ps->flag_mutex); //rv = ps_process_raw(ps->ps, (int16 *) data, len / 2, FALSE, FALSE); /* chenbingfeng*/ ret = QISRAudioWrite(ps->ifly_session_id, (const void *)data, len, ps->ifly_aud_stat, &(ps->ifly_ep_stat), &(ps->ifly_rec_stat)); if (MSP_SUCCESS != ret) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "\nQISRAudioWrite failed! error code:%d\n", ret); } switch_mutex_unlock(ps->flag_mutex); } if (rv < 0) { return SWITCH_STATUS_FALSE; } } else if (switch_test_flag(ps, PSFLAG_NOINPUT_TIMEOUT)) { /* never heard anything */ switch_clear_flag_locked(ps, PSFLAG_READY); } return SWITCH_STATUS_SUCCESS; }