2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2019, Anthony Minessale II <anthm@freeswitch.org>
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Paul D. Tinsley <pdt at jackhammer.org>
28 * Neal Horman <neal at wanlink dot com>
29 * Matt Klein <mklein@nmedia.net>
30 * Michael Jerris <mike@jerris.com>
31 * Marc Olivier Chouinard <mochouinard@moctel.com>
33 * switch_ivr_play_say.c -- IVR Library (functions to play or say audio)
39 SWITCH_DECLARE(switch_status_t
) switch_ivr_phrase_macro_event(switch_core_session_t
*session
, const char *macro_name
, const char *data
, switch_event_t
*event
, const char *lang
,
40 switch_input_args_t
*args
)
42 switch_event_t
*hint_data
;
43 switch_xml_t cfg
, xml
= NULL
, language
= NULL
, macros
= NULL
, phrases
= NULL
, macro
, input
, action
;
44 switch_status_t status
= SWITCH_STATUS_GENERR
;
45 const char *old_sound_prefix
= NULL
, *sound_path
= NULL
, *tts_engine
= NULL
, *tts_voice
= NULL
;
46 const char *module_name
= NULL
, *chan_lang
= NULL
;
47 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
48 uint8_t done
= 0, searched
= 0;
50 const char *pause_val
;
52 const char *group_macro_name
= NULL
;
53 const char *local_macro_name
= macro_name
;
54 switch_bool_t sound_prefix_enforced
= switch_true(switch_channel_get_variable(channel
, "sound_prefix_enforced"));
55 switch_bool_t local_sound_prefix_enforced
= SWITCH_FALSE
;
59 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No phrase macro specified.\n");
63 arg_recursion_check_start(args
);
66 chan_lang
= switch_channel_get_variable(channel
, "default_language");
70 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "No language specified - Using [%s]\n", chan_lang
);
75 switch_event_create(&hint_data
, SWITCH_EVENT_REQUEST_PARAMS
);
76 switch_assert(hint_data
);
78 switch_event_add_header_string(hint_data
, SWITCH_STACK_BOTTOM
, "macro_name", macro_name
);
79 switch_event_add_header_string(hint_data
, SWITCH_STACK_BOTTOM
, "lang", chan_lang
);
81 switch_event_add_header_string(hint_data
, SWITCH_STACK_BOTTOM
, "data", data
);
83 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "data", data
);
88 switch_channel_event_set_data(channel
, hint_data
);
90 if (switch_xml_locate_language(&xml
, &cfg
, hint_data
, &language
, &phrases
, ¯os
, chan_lang
) != SWITCH_STATUS_SUCCESS
) {
94 if ((module_name
= switch_xml_attr(language
, "say-module"))) {
95 } else if ((module_name
= switch_xml_attr(language
, "module"))) {
96 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Deprecated usage of module attribute. Use say-module instead\n");
98 module_name
= chan_lang
;
101 if (!(sound_path
= (char *) switch_xml_attr(language
, "sound-prefix"))) {
102 if (!(sound_path
= (char *) switch_xml_attr(language
, "sound-path"))) {
103 sound_path
= (char *) switch_xml_attr(language
, "sound_path");
107 if (!(tts_engine
= (char *) switch_xml_attr(language
, "tts-engine"))) {
108 tts_engine
= (char *) switch_xml_attr(language
, "tts_engine");
111 if (!(tts_voice
= (char *) switch_xml_attr(language
, "tts-voice"))) {
112 tts_voice
= (char *) switch_xml_attr(language
, "tts_voice");
115 /* If we use the new structure, check for a group name */
116 if (language
!= macros
) {
118 char *macro_name_dup
= switch_core_session_strdup(session
, macro_name
);
119 const char *group_sound_path
;
120 const char *sound_prefix_enforced_str
;
122 if ((p
= strchr(macro_name_dup
, '@'))) {
124 local_macro_name
= macro_name_dup
;
125 group_macro_name
= p
;
127 if (!(macros
= switch_xml_find_child(phrases
, "macros", "name", group_macro_name
))) {
128 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Can't find macros group %s.\n", group_macro_name
);
132 /* Support override of certain language attribute */
133 if ((group_sound_path
= (char *) switch_xml_attr(macros
, "sound-prefix")) || (group_sound_path
= (char *) switch_xml_attr(macros
, "sound-path")) || (group_sound_path
= (char *) switch_xml_attr(macros
, "sound_path"))) {
134 sound_path
= group_sound_path
;
137 if (sound_prefix_enforced
== SWITCH_FALSE
&& (sound_prefix_enforced_str
= switch_xml_attr(macros
, "sound-prefix-enforced"))
138 && (local_sound_prefix_enforced
= switch_true(sound_prefix_enforced_str
)) == SWITCH_TRUE
) {
139 switch_channel_set_variable(channel
, "sound_prefix_enforced", sound_prefix_enforced_str
);
144 if (!(macro
= switch_xml_find_child(macros
, "macro", "name", local_macro_name
))) {
145 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Can't find macro %s.\n", macro_name
);
149 if (sound_path
&& sound_prefix_enforced
== SWITCH_FALSE
) {
151 old_sound_prefix
= switch_str_nil(switch_channel_get_variable(channel
, "sound_prefix"));
152 p
= switch_core_session_strdup(session
, old_sound_prefix
);
153 old_sound_prefix
= p
;
154 switch_channel_set_variable(channel
, "sound_prefix", sound_path
);
157 if ((pause_val
= switch_xml_attr(macro
, "pause"))) {
158 int tmp
= atoi(pause_val
);
164 if (!(input
= switch_xml_child(macro
, "input"))) {
165 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Can't find any input tags.\n");
169 if (switch_channel_pre_answer(channel
) != SWITCH_STATUS_SUCCESS
) {
170 status
= SWITCH_STATUS_FALSE
;
175 char *field
= (char *) switch_xml_attr(input
, "field");
176 char *pattern
= (char *) switch_xml_attr(input
, "pattern");
177 const char *do_break
= switch_xml_attr_soft(input
, "break_on_match");
178 char *field_expanded
= NULL
;
179 char *field_expanded_alloc
= NULL
;
180 switch_regex_t
*re
= NULL
;
181 int proceed
= 0, ovector
[100];
182 switch_xml_t match
= NULL
;
186 field
= (char *) data
;
189 field_expanded_alloc
= switch_event_expand_headers(event
, field
);
191 field_expanded_alloc
= switch_channel_expand_variables(channel
, field
);
194 if (field_expanded_alloc
== field
) {
195 field_expanded_alloc
= NULL
;
196 field_expanded
= field
;
198 field_expanded
= field_expanded_alloc
;
205 status
= SWITCH_STATUS_SUCCESS
;
207 if ((proceed
= switch_regex_perform(field_expanded
, pattern
, &re
, ovector
, sizeof(ovector
) / sizeof(ovector
[0])))) {
208 match
= switch_xml_child(input
, "match");
210 match
= switch_xml_child(input
, "nomatch");
215 for (action
= switch_xml_child(match
, "action"); action
; action
= action
->next
) {
216 char *adata
= (char *) switch_xml_attr_soft(action
, "data");
217 char *func
= (char *) switch_xml_attr_soft(action
, "function");
218 char *substituted
= NULL
;
221 char *expanded
= NULL
;
223 if (strchr(pattern
, '(') && strchr(adata
, '$') && proceed
> 0) {
224 len
= (uint32_t) (strlen(data
) + strlen(adata
) + 10) * proceed
;
225 if (!(substituted
= malloc(len
))) {
226 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Memory Error!\n");
227 switch_regex_safe_free(re
);
228 switch_safe_free(field_expanded_alloc
);
231 memset(substituted
, 0, len
);
232 switch_perform_substitution(re
, proceed
, adata
, field_expanded
, substituted
, len
, ovector
);
239 expanded
= switch_event_expand_headers(event
, odata
);
241 expanded
= switch_channel_expand_variables(channel
, odata
);
244 if (expanded
== odata
) {
250 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "Handle %s:[%s] (%s:%s)\n", func
, odata
, chan_lang
,
253 if (!strcasecmp(func
, "play-file")) {
254 char *volume_str
= (char *) switch_xml_attr_soft(action
, "volume");
255 switch_file_handle_t pfh
= { 0 };
256 if (volume_str
&& switch_is_number(volume_str
)) {
257 int32_t volume
= atoi(volume_str
);
259 switch_normalize_volume_granular(volume
)
260 pfh
.volgranular
= volume
;
262 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "Setting playback volume to %d\n", pfh
.volgranular
);
264 status
= switch_ivr_play_file(session
, &pfh
, odata
, args
);
265 } else if (!strcasecmp(func
, "phrase")) {
266 char *name
= (char *) switch_xml_attr_soft(action
, "phrase");
267 status
= switch_ivr_phrase_macro(session
, name
, odata
, chan_lang
, args
);
268 } else if (!strcasecmp(func
, "break")) {
269 done
= 1; /* don't break or we leak memory */
270 } else if (!strcasecmp(func
, "execute")) {
271 switch_application_interface_t
*app
;
272 char *cmd
, *cmd_args
;
273 status
= SWITCH_STATUS_FALSE
;
275 cmd
= switch_core_session_strdup(session
, odata
);
276 cmd_args
= switch_separate_paren_args(cmd
);
282 if ((app
= switch_loadable_module_get_application_interface(cmd
)) != NULL
) {
283 status
= switch_core_session_exec(session
, app
, cmd_args
);
284 UNPROTECT_INTERFACE(app
);
286 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Invalid Application %s\n", cmd
);
288 } else if (!strcasecmp(func
, "say")) {
289 switch_say_interface_t
*si
;
290 if ((si
= switch_loadable_module_get_say_interface(module_name
))) {
291 char *say_type
= (char *) switch_xml_attr_soft(action
, "type");
292 char *say_method
= (char *) switch_xml_attr_soft(action
, "method");
293 char *say_gender
= (char *) switch_xml_attr_soft(action
, "gender");
294 switch_say_args_t say_args
= {0};
296 say_args
.type
= switch_ivr_get_say_type_by_name(say_type
);
297 say_args
.method
= switch_ivr_get_say_method_by_name(say_method
);
298 say_args
.gender
= switch_ivr_get_say_gender_by_name(say_gender
);
300 status
= si
->say_function(session
, odata
, &say_args
, args
);
302 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Invalid SAY Interface [%s]!\n", module_name
);
304 } else if (!strcasecmp(func
, "speak-text")) {
305 const char *my_tts_engine
= switch_xml_attr(action
, "tts-engine");
306 const char *my_tts_voice
= switch_xml_attr(action
, "tts-voice");
308 if (!my_tts_engine
) {
309 my_tts_engine
= tts_engine
;
313 my_tts_voice
= tts_voice
;
315 if (zstr(tts_engine
) || zstr(tts_voice
)) {
316 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "TTS is not configured\n");
318 status
= switch_ivr_speak_text(session
, my_tts_engine
, my_tts_voice
, odata
, args
);
322 switch_ivr_sleep(session
, pause
, SWITCH_FALSE
, NULL
);
323 switch_safe_free(expanded
);
324 switch_safe_free(substituted
);
325 if (done
|| status
!= SWITCH_STATUS_SUCCESS
) break;
329 switch_regex_safe_free(re
);
330 switch_safe_free(field_expanded_alloc
);
332 if (done
|| status
!= SWITCH_STATUS_SUCCESS
333 || (match
&& do_break
&& switch_true(do_break
))) {
342 arg_recursion_check_stop(args
);
345 switch_event_destroy(&hint_data
);
348 if (searched
&& !matches
) {
349 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Macro [%s]: '%s' did not match any patterns\n", macro_name
, data
);
352 if (old_sound_prefix
) {
353 switch_channel_set_variable(channel
, "sound_prefix", old_sound_prefix
);
355 if (local_sound_prefix_enforced
== SWITCH_TRUE
) {
356 switch_channel_set_variable(channel
, "sound_prefix_enforced", NULL
);
360 switch_xml_free(xml
);
366 static void merge_recording_variables(switch_event_t
*vars
, switch_event_t
*event
)
368 switch_event_header_t
*hi
;
370 for (hi
= vars
->headers
; hi
; hi
= hi
->next
) {
372 char *vvar
= NULL
, *vval
= NULL
;
374 vvar
= (char *) hi
->name
;
375 vval
= (char *) hi
->value
;
377 switch_assert(vvar
&& vval
);
378 switch_snprintf(buf
, sizeof(buf
), "Recording-Variable-%s", vvar
);
379 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, buf
, vval
);
384 static const char *get_recording_var(switch_channel_t
*channel
, switch_event_t
*vars
, switch_file_handle_t
*fh
, const char *name
)
386 const char *val
= NULL
;
388 val
= switch_event_get_header(vars
, name
);
390 if (!val
&& fh
&& fh
->params
) {
391 val
= switch_event_get_header(fh
->params
, name
);
394 val
= switch_channel_get_variable(channel
, name
);
399 static int recording_var_true(switch_channel_t
*channel
, switch_event_t
*vars
, switch_file_handle_t
*fh
, const char *name
)
401 return switch_true(get_recording_var(channel
, vars
, fh
, name
));
404 SWITCH_DECLARE(switch_status_t
) switch_ivr_record_file_event(switch_core_session_t
*session
,
405 switch_file_handle_t
*fh
, const char *file
, switch_input_args_t
*args
, uint32_t limit
, switch_event_t
*vars
)
407 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
408 switch_dtmf_t dtmf
= { 0 };
409 switch_file_handle_t lfh
= { 0 };
410 switch_file_handle_t vfh
= { 0 };
411 switch_file_handle_t ind_fh
= { 0 };
412 switch_frame_t
*read_frame
;
413 switch_codec_t codec
, write_codec
= { 0 };
415 switch_status_t status
= SWITCH_STATUS_SUCCESS
;
419 uint32_t org_silence_hits
= 0;
421 int32_t sample_start
= 0;
422 int waste_resources
= 1400, fill_cng
= 0;
423 switch_codec_implementation_t read_impl
= { 0 };
424 switch_frame_t write_frame
= { 0 };
425 unsigned char write_buf
[SWITCH_RECOMMENDED_BUFFER_SIZE
] = { 0 };
426 switch_event_t
*event
;
428 int file_flags
= SWITCH_FILE_FLAG_WRITE
| SWITCH_FILE_DATA_SHORT
;
429 int restart_limit_on_dtmf
= 0;
430 const char *prefix
, *var
, *video_file
= NULL
;
431 int vid_play_file_flags
= SWITCH_FILE_FLAG_READ
| SWITCH_FILE_DATA_SHORT
| SWITCH_FILE_FLAG_VIDEO
;
433 const char *file_trimmed_ms
= NULL
;
434 const char *file_size
= NULL
;
435 const char *file_trimmed
= NULL
;
437 if (switch_channel_pre_answer(channel
) != SWITCH_STATUS_SUCCESS
) {
438 return SWITCH_STATUS_FALSE
;
442 return SWITCH_STATUS_FALSE
;
445 prefix
= get_recording_var(channel
, vars
, fh
, "sound_prefix");
448 prefix
= SWITCH_GLOBAL_dirs
.sounds_dir
;
451 if (!switch_channel_media_ready(channel
)) {
452 return SWITCH_STATUS_FALSE
;
455 switch_core_session_get_read_impl(session
, &read_impl
);
457 if (!(divisor
= read_impl
.actual_samples_per_second
/ 8000)) {
461 arg_recursion_check_start(args
);
467 fh
->channels
= read_impl
.number_of_channels
;
468 fh
->native_rate
= read_impl
.actual_samples_per_second
;
470 if (fh
->samples
> 0) {
471 sample_start
= fh
->samples
;
476 if ((p
= get_recording_var(channel
, vars
, fh
, "record_sample_rate"))) {
481 if (switch_is_valid_rate(tmp
)) {
482 fh
->samplerate
= tmp
;
486 if (!strstr(file
, SWITCH_URL_SEPARATOR
)) {
489 if (!switch_is_file_path(file
)) {
494 tfile
= switch_core_session_strdup(session
, file
);
496 while (*file
== '{') {
497 if ((e
= switch_find_end_paren(tfile
, '{', '}'))) {
500 while(*file
== ' ') file
++;
508 file
= switch_core_session_sprintf(session
, "%s%s%s%s%s", switch_str_nil(tfile
), tfile
? "}" : "", prefix
, SWITCH_PATH_SEPARATOR
, file
);
510 if ((ext
= strrchr(file
, '.'))) {
513 ext
= read_impl
.iananame
;
514 file
= switch_core_session_sprintf(session
, "%s.%s", file
, ext
);
519 if (asis
&& read_impl
.encoded_bytes_per_packet
== 0) {
520 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "%s cannot play or record native files with variable length data\n", switch_channel_get_name(channel
));
521 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_TRUE
);
522 arg_recursion_check_stop(args
);
523 return SWITCH_STATUS_GENERR
;
527 vval
= get_recording_var(channel
, vars
, fh
, "enable_file_write_buffering");
528 if (!vval
|| switch_true(vval
)) {
529 fh
->pre_buffer_datalen
= SWITCH_DEFAULT_FILE_BUFFER_LEN
;
532 if (switch_test_flag(fh
, SWITCH_FILE_WRITE_APPEND
) || recording_var_true(channel
, vars
, fh
, "RECORD_APPEND")) {
533 file_flags
|= SWITCH_FILE_WRITE_APPEND
;
536 if (switch_test_flag(fh
, SWITCH_FILE_WRITE_OVER
) || recording_var_true(channel
, vars
, fh
, "RECORD_WRITE_OVER")) {
537 file_flags
|= SWITCH_FILE_WRITE_OVER
;
544 if (switch_channel_test_flag(channel
, CF_VIDEO
)) {
545 switch_vid_params_t vid_params
= { 0 };
547 file_flags
|= SWITCH_FILE_FLAG_VIDEO
;
548 switch_channel_set_flag_recursive(channel
, CF_VIDEO_DECODED_READ
);
549 switch_core_session_request_video_refresh(session
);
550 if (switch_core_session_wait_for_video_input_params(session
, 10000) != SWITCH_STATUS_SUCCESS
) {
551 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Unable to establish inbound video stream\n");
552 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_TRUE
);
553 arg_recursion_check_stop(args
);
554 file_flags
&= ~SWITCH_FILE_FLAG_VIDEO
;
556 switch_core_media_get_vid_params(session
, &vid_params
);
557 fh
->mm
.vw
= vid_params
.width
;
558 fh
->mm
.vh
= vid_params
.height
;
559 fh
->mm
.fps
= vid_params
.fps
;
563 if (switch_core_file_open(fh
, file
, fh
->channels
, read_impl
.actual_samples_per_second
, file_flags
, NULL
) != SWITCH_STATUS_SUCCESS
) {
564 switch_channel_hangup(channel
, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
);
565 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_TRUE
);
566 arg_recursion_check_stop(args
);
567 return SWITCH_STATUS_GENERR
;
571 if ((p
= get_recording_var(channel
, vars
, fh
, "record_fill_cng"))) {
572 if (!strcasecmp(p
, "true")) {
575 if ((fill_cng
= atoi(p
)) < 0) {
581 if ((p
= switch_channel_get_variable(channel
, "record_indication")) || (fh
->params
&& (p
= switch_event_get_header(fh
->params
, "record_indication")))) {
582 int flags
= SWITCH_FILE_FLAG_READ
| SWITCH_FILE_DATA_SHORT
;
583 waste_resources
= 1400;
585 if (switch_core_file_open(&ind_fh
,
587 read_impl
.number_of_channels
,
588 read_impl
.actual_samples_per_second
, flags
, NULL
) != SWITCH_STATUS_SUCCESS
) {
589 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Indication file invalid\n");
593 if ((p
= get_recording_var(channel
, vars
, fh
, "record_waste_resources"))) {
595 if (!strcasecmp(p
, "true")) {
596 waste_resources
= 1400;
598 if ((waste_resources
= atoi(p
)) < 0) {
604 if (fill_cng
|| waste_resources
) {
605 if (switch_core_codec_init(&write_codec
,
609 read_impl
.actual_samples_per_second
,
610 read_impl
.microseconds_per_packet
/ 1000,
611 read_impl
.number_of_channels
,
612 SWITCH_CODEC_FLAG_ENCODE
| SWITCH_CODEC_FLAG_DECODE
, NULL
,
613 switch_core_session_get_pool(session
)) == SWITCH_STATUS_SUCCESS
) {
614 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "Raw Codec Activated, ready to waste resources!\n");
615 write_frame
.data
= write_buf
;
616 write_frame
.buflen
= sizeof(write_buf
);
617 write_frame
.datalen
= read_impl
.decoded_bytes_per_packet
;
618 write_frame
.samples
= write_frame
.datalen
/ 2;
619 write_frame
.codec
= &write_codec
;
621 arg_recursion_check_stop(args
);
622 return SWITCH_STATUS_FALSE
;
628 if (switch_core_file_has_video(fh
, SWITCH_TRUE
)) {
629 switch_core_session_request_video_refresh(session
);
631 if ((p
= get_recording_var(channel
, vars
, fh
, "record_play_video"))) {
633 video_file
= switch_core_session_strdup(session
, p
);
635 if (switch_core_file_open(&vfh
, video_file
, fh
->channels
,
636 read_impl
.actual_samples_per_second
, vid_play_file_flags
, NULL
) != SWITCH_STATUS_SUCCESS
) {
637 memset(&vfh
, 0, sizeof(vfh
));
638 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failure opening video playback file.\n");
641 if (switch_core_file_has_video(&vfh
, SWITCH_TRUE
)) {
642 switch_core_media_set_video_file(session
, &vfh
, SWITCH_RW_WRITE
);
643 switch_core_media_gen_key_frame(session
);
645 switch_core_file_close(&vfh
);
646 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Video playback file does not contain video\n");
647 memset(&vfh
, 0, sizeof(vfh
));
651 if (!switch_test_flag(&vfh
, SWITCH_FILE_OPEN
)) {
653 switch_channel_set_flag_recursive(channel
, CF_VIDEO_DECODED_READ
);
654 switch_channel_set_flag(channel
, CF_VIDEO_ECHO
);
657 switch_core_media_set_video_file(session
, fh
, SWITCH_RW_READ
);
658 } else if (switch_channel_test_flag(channel
, CF_VIDEO
)) {
659 switch_channel_set_flag(channel
, CF_VIDEO_BLANK
);
662 if (sample_start
> 0) {
664 switch_core_file_seek(fh
, &pos
, sample_start
, SEEK_SET
);
665 switch_clear_flag_locked(fh
, SWITCH_FILE_SEEK
);
670 if (switch_test_flag(fh
, SWITCH_FILE_NATIVE
)) {
674 restart_limit_on_dtmf
= recording_var_true(channel
, vars
, fh
, "record_restart_limit_on_dtmf");
676 if ((p
= get_recording_var(channel
, vars
, fh
, "record_title"))) {
677 vval
= switch_core_session_strdup(session
, p
);
678 switch_core_file_set_string(fh
, SWITCH_AUDIO_COL_STR_TITLE
, vval
);
679 switch_channel_set_variable(channel
, "record_title", NULL
);
682 if ((p
= get_recording_var(channel
, vars
, fh
, "record_copyright"))) {
683 vval
= switch_core_session_strdup(session
, p
);
684 switch_core_file_set_string(fh
, SWITCH_AUDIO_COL_STR_COPYRIGHT
, vval
);
685 switch_channel_set_variable(channel
, "record_copyright", NULL
);
688 if ((p
= get_recording_var(channel
, vars
, fh
, "record_software"))) {
689 vval
= switch_core_session_strdup(session
, p
);
690 switch_core_file_set_string(fh
, SWITCH_AUDIO_COL_STR_SOFTWARE
, vval
);
691 switch_channel_set_variable(channel
, "record_software", NULL
);
694 if ((p
= get_recording_var(channel
, vars
, fh
, "record_artist"))) {
695 vval
= switch_core_session_strdup(session
, p
);
696 switch_core_file_set_string(fh
, SWITCH_AUDIO_COL_STR_ARTIST
, vval
);
697 switch_channel_set_variable(channel
, "record_artist", NULL
);
700 if ((p
= get_recording_var(channel
, vars
, fh
, "record_comment"))) {
701 vval
= switch_core_session_strdup(session
, p
);
702 switch_core_file_set_string(fh
, SWITCH_AUDIO_COL_STR_COMMENT
, vval
);
703 switch_channel_set_variable(channel
, "record_comment", NULL
);
706 if ((p
= get_recording_var(channel
, vars
, fh
, "record_date"))) {
707 vval
= switch_core_session_strdup(session
, p
);
708 switch_core_file_set_string(fh
, SWITCH_AUDIO_COL_STR_DATE
, vval
);
709 switch_channel_set_variable(channel
, "record_date", NULL
);
713 switch_channel_set_variable(channel
, "silence_hits_exhausted", "false");
717 if (switch_core_codec_init(&codec
,
721 read_impl
.actual_samples_per_second
,
722 read_impl
.microseconds_per_packet
/ 1000,
723 read_impl
.number_of_channels
,
724 SWITCH_CODEC_FLAG_ENCODE
| SWITCH_CODEC_FLAG_DECODE
, NULL
,
725 switch_core_session_get_pool(session
)) == SWITCH_STATUS_SUCCESS
) {
726 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "Raw Codec Activated\n");
727 switch_core_session_set_read_codec(session
, &codec
);
729 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
,
730 "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name
, fh
->samplerate
,
731 fh
->channels
, read_impl
.microseconds_per_packet
/ 1000);
732 if (switch_core_file_has_video(fh
, SWITCH_FALSE
)) {
734 switch_channel_clear_flag(channel
, CF_VIDEO_ECHO
);
735 switch_channel_clear_flag_recursive(channel
, CF_VIDEO_DECODED_READ
);
737 switch_core_media_set_video_file(session
, NULL
, SWITCH_RW_READ
);
738 switch_core_media_set_video_file(session
, NULL
, SWITCH_RW_WRITE
);
740 switch_channel_clear_flag(channel
, CF_VIDEO_BLANK
);
741 switch_core_file_close(fh
);
743 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_TRUE
);
744 arg_recursion_check_stop(args
);
745 return SWITCH_STATUS_GENERR
;
750 start
= switch_epoch_time_now(NULL
);
755 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Can't detect silence on a native recording.\n");
757 if (fh
->silence_hits
) {
758 fh
->silence_hits
= fh
->samplerate
* fh
->silence_hits
/ read_impl
.samples_per_packet
;
760 fh
->silence_hits
= fh
->samplerate
* 3 / read_impl
.samples_per_packet
;
762 org_silence_hits
= fh
->silence_hits
;
767 if (switch_event_create(&event
, SWITCH_EVENT_RECORD_START
) == SWITCH_STATUS_SUCCESS
) {
768 switch_channel_event_set_data(channel
, event
);
769 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "Record-File-Path", file
);
770 merge_recording_variables(vars
, event
);
771 switch_event_fire(&event
);
775 const char *app_exec
= NULL
;
776 if (vars
&& (app_exec
= switch_event_get_header(vars
, "execute_on_record_start"))) {
777 switch_channel_execute_on_value(channel
, app_exec
);
779 switch_channel_execute_on(channel
, "execute_on_record_start");
780 switch_channel_api_on(channel
, "api_on_record_start");
786 if (!switch_channel_ready(channel
)) {
787 status
= SWITCH_STATUS_FALSE
;
791 if (switch_channel_test_flag(channel
, CF_BREAK
)) {
792 switch_channel_clear_flag(channel
, CF_BREAK
);
793 status
= SWITCH_STATUS_BREAK
;
797 switch_ivr_parse_all_events(session
);
799 if (start
&& (switch_epoch_time_now(NULL
) - start
) > limit
) {
805 dtmf handler function you can hook up to be executed when a digit is dialed during playback
806 if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
808 if (switch_channel_has_dtmf(channel
)) {
810 if (limit
&& restart_limit_on_dtmf
) {
811 start
= switch_epoch_time_now(NULL
);
814 if (!args
->input_callback
&& !args
->buf
&& !args
->dmachine
) {
815 status
= SWITCH_STATUS_BREAK
;
818 switch_channel_dequeue_dtmf(channel
, &dtmf
);
820 if (args
->dmachine
) {
821 char ds
[2] = {dtmf
.digit
, '\0'};
822 if ((status
= switch_ivr_dmachine_feed(args
->dmachine
, ds
, NULL
)) != SWITCH_STATUS_SUCCESS
) {
827 if (args
->input_callback
) {
828 status
= args
->input_callback(session
, (void *) &dtmf
, SWITCH_INPUT_TYPE_DTMF
, args
->buf
, args
->buflen
);
829 } else if (args
->buf
) {
830 *((char *) args
->buf
) = dtmf
.digit
;
831 status
= SWITCH_STATUS_BREAK
;
835 if (args
->input_callback
) {
836 switch_event_t
*event
= NULL
;
837 switch_status_t ostatus
;
839 if (switch_core_session_dequeue_event(session
, &event
, SWITCH_FALSE
) == SWITCH_STATUS_SUCCESS
) {
840 if ((ostatus
= args
->input_callback(session
, event
, SWITCH_INPUT_TYPE_EVENT
, args
->buf
, args
->buflen
)) != SWITCH_STATUS_SUCCESS
) {
844 switch_event_destroy(&event
);
848 if (status
!= SWITCH_STATUS_SUCCESS
) {
853 status
= switch_core_session_read_frame(session
, &read_frame
, SWITCH_IO_FLAG_NONE
, 0);
854 if (!SWITCH_READ_ACCEPTABLE(status
)) {
858 if (args
&& args
->dmachine
) {
859 if ((status
= switch_ivr_dmachine_ping(args
->dmachine
, NULL
)) != SWITCH_STATUS_SUCCESS
) {
864 if (args
&& (args
->read_frame_callback
)) {
865 if ((status
= args
->read_frame_callback(session
, read_frame
, args
->user_data
)) != SWITCH_STATUS_SUCCESS
) {
870 if (switch_test_flag(&vfh
, SWITCH_FILE_OPEN
)) {
871 switch_core_file_command(&vfh
, SCFC_FLUSH_AUDIO
);
873 if (switch_test_flag(&vfh
, SWITCH_FILE_FLAG_VIDEO_EOF
)) {
875 //switch_core_media_set_video_file(session, NULL, SWITCH_RW_WRITE);
877 switch_core_media_lock_video_file(session
, SWITCH_RW_WRITE
);
879 switch_core_file_close(&vfh
);
880 memset(&vfh
, 0, sizeof(vfh
));
882 if (switch_core_file_open(&vfh
, video_file
, fh
->channels
,
883 read_impl
.actual_samples_per_second
, vid_play_file_flags
, NULL
) != SWITCH_STATUS_SUCCESS
) {
884 memset(&vfh
, 0, sizeof(vfh
));
885 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failure opening video playback file.\n");
888 if (switch_core_file_has_video(&vfh
, SWITCH_TRUE
)) {
889 //switch_core_media_set_video_file(session, &vfh, SWITCH_RW_WRITE);
890 switch_core_media_gen_key_frame(session
);
892 switch_core_media_set_video_file(session
, NULL
, SWITCH_RW_WRITE
);
893 switch_core_file_close(&vfh
);
894 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Video playback file does not contain video\n");
895 memset(&vfh
, 0, sizeof(vfh
));
898 switch_core_media_unlock_video_file(session
, SWITCH_RW_WRITE
);
903 if (!asis
&& fh
->thresh
) {
904 int16_t *fdata
= (int16_t *) read_frame
->data
;
905 uint32_t samples
= read_frame
->datalen
/ sizeof(*fdata
);
906 uint32_t score
, count
= 0, j
= 0;
910 for (count
= 0; count
< samples
* read_impl
.number_of_channels
; count
++) {
911 energy
+= abs(fdata
[j
++]);
914 score
= (uint32_t) (energy
/ (samples
/ divisor
));
916 if (score
< fh
->thresh
) {
917 if (!--fh
->silence_hits
) {
918 switch_channel_set_variable(channel
, "silence_hits_exhausted", "true");
922 fh
->silence_hits
= org_silence_hits
;
926 write_frame
.datalen
= read_impl
.decoded_bytes_per_packet
;
927 write_frame
.samples
= write_frame
.datalen
/ 2;
929 if (switch_test_flag(&ind_fh
, SWITCH_FILE_OPEN
)) {
930 switch_size_t olen
= write_frame
.codec
->implementation
->samples_per_packet
;
932 if (switch_core_file_read(&ind_fh
, write_frame
.data
, &olen
) == SWITCH_STATUS_SUCCESS
) {
933 write_frame
.samples
= olen
;
934 write_frame
.datalen
= olen
* 2 * ind_fh
.channels
;;
936 switch_core_file_close(&ind_fh
);
939 } else if (fill_cng
) {
940 switch_generate_sln_silence((int16_t *) write_frame
.data
, write_frame
.samples
, read_impl
.number_of_channels
, fill_cng
);
941 } else if (waste_resources
) {
942 switch_generate_sln_silence((int16_t *) write_frame
.data
, write_frame
.samples
, read_impl
.number_of_channels
, waste_resources
);
945 if (!switch_test_flag(fh
, SWITCH_FILE_PAUSE
) && !switch_test_flag(read_frame
, SFF_CNG
)) {
946 int16_t *data
= read_frame
->data
;
947 len
= (switch_size_t
) asis
? read_frame
->datalen
: read_frame
->datalen
/ 2 / fh
->channels
;
949 if (switch_core_file_write(fh
, data
, &len
) != SWITCH_STATUS_SUCCESS
) {
952 } else if (switch_test_flag(read_frame
, SFF_CNG
) && fill_cng
) {
953 len
= write_frame
.datalen
/ 2 / fh
->channels
;
954 if (switch_core_file_write(fh
, write_frame
.data
, &len
) != SWITCH_STATUS_SUCCESS
) {
960 if (waste_resources
|| switch_test_flag(&ind_fh
, SWITCH_FILE_OPEN
)) {
961 if (switch_core_session_write_frame(session
, &write_frame
, SWITCH_IO_FLAG_NONE
, 0) != SWITCH_STATUS_SUCCESS
) {
967 if (fill_cng
|| waste_resources
) {
968 switch_core_codec_destroy(&write_codec
);
971 if (switch_core_file_has_video(fh
, SWITCH_FALSE
)) {
973 switch_channel_clear_flag(channel
, CF_VIDEO_ECHO
);
974 switch_channel_clear_flag_recursive(channel
, CF_VIDEO_DECODED_READ
);
976 switch_core_media_set_video_file(session
, NULL
, SWITCH_RW_READ
);
977 switch_core_media_set_video_file(session
, NULL
, SWITCH_RW_WRITE
);
979 switch_channel_clear_flag(channel
, CF_VIDEO_BLANK
);
981 switch_core_file_pre_close(fh
);
982 switch_core_file_get_string(fh
, SWITCH_AUDIO_COL_STR_FILE_SIZE
, &file_size
);
983 switch_core_file_get_string(fh
, SWITCH_AUDIO_COL_STR_FILE_TRIMMED
, &file_trimmed
);
984 switch_core_file_get_string(fh
, SWITCH_AUDIO_COL_STR_FILE_TRIMMED_MS
, &file_trimmed_ms
);
985 if (file_trimmed_ms
) {
986 switch_channel_set_variable(channel
, "record_record_trimmed_ms", file_trimmed_ms
);
987 switch_channel_set_variable(channel
, "record_trimmed_ms", file_trimmed_ms
);
990 switch_channel_set_variable(channel
, "record_record_file_size", file_size
);
991 switch_channel_set_variable(channel
, "record_file_size", file_size
);
994 switch_channel_set_variable(channel
, "record_record_trimmed", file_trimmed
);
995 switch_channel_set_variable(channel
, "record_trimmed", file_trimmed
);
997 switch_core_file_close(fh
);
1000 if ((var
= switch_channel_get_variable(channel
, "record_post_process_exec_api"))) {
1001 char *cmd
= switch_core_session_strdup(session
, var
);
1002 char *data
, *expanded
= NULL
;
1003 switch_stream_handle_t stream
= { 0 };
1005 SWITCH_STANDARD_STREAM(stream
);
1007 if ((data
= strchr(cmd
, ':'))) {
1009 expanded
= switch_channel_expand_variables(channel
, data
);
1012 switch_api_execute(cmd
, expanded
, session
, &stream
);
1014 if (expanded
&& expanded
!= data
) {
1018 switch_safe_free(stream
.data
);
1022 if (read_impl
.actual_samples_per_second
&& fh
->native_rate
>= 1000) {
1023 switch_channel_set_variable_printf(channel
, "record_seconds", "%d", fh
->samples_out
/ fh
->native_rate
);
1024 switch_channel_set_variable_printf(channel
, "record_ms", "%d", fh
->samples_out
/ (fh
->native_rate
/ 1000));
1028 switch_channel_set_variable_printf(channel
, "record_samples", "%d", fh
->samples_out
);
1030 if (switch_event_create(&event
, SWITCH_EVENT_RECORD_STOP
) == SWITCH_STATUS_SUCCESS
) {
1031 switch_channel_event_set_data(channel
, event
);
1032 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "Record-File-Path", file
);
1033 merge_recording_variables(vars
, event
);
1034 switch_event_fire(&event
);
1038 const char *app_exec
= NULL
;
1039 if (vars
&& (app_exec
= switch_event_get_header(vars
, "execute_on_record_stop"))) {
1040 switch_channel_execute_on_value(channel
, app_exec
);
1042 switch_channel_execute_on(channel
, "execute_on_record_stop");
1043 switch_channel_api_on(channel
, "api_on_record_stop");
1046 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_TRUE
);
1048 arg_recursion_check_stop(args
);
1052 SWITCH_DECLARE(switch_status_t
) switch_ivr_record_file(switch_core_session_t
*session
,
1053 switch_file_handle_t
*fh
, const char *file
, switch_input_args_t
*args
, uint32_t limit
)
1055 return switch_ivr_record_file_event(session
, fh
, file
, args
, limit
, NULL
);
1058 static int teletone_handler(teletone_generation_session_t
*ts
, teletone_tone_map_t
*map
)
1060 switch_buffer_t
*audio_buffer
= ts
->user_data
;
1063 if (!audio_buffer
) {
1067 wrote
= teletone_mux_tones(ts
, map
);
1068 switch_buffer_write(audio_buffer
, ts
->buffer
, wrote
* 2);
1073 SWITCH_DECLARE(switch_status_t
) switch_ivr_gentones(switch_core_session_t
*session
, const char *script
, int32_t loops
, switch_input_args_t
*args
)
1075 teletone_generation_session_t ts
;
1076 switch_dtmf_t dtmf
= { 0 };
1077 switch_buffer_t
*audio_buffer
;
1078 switch_frame_t
*read_frame
= NULL
;
1079 switch_codec_t write_codec
= { 0 };
1080 switch_frame_t write_frame
= { 0 };
1081 switch_byte_t data
[SWITCH_RECOMMENDED_BUFFER_SIZE
];
1082 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
1083 switch_codec_implementation_t read_impl
= { 0 };
1084 switch_core_session_get_read_impl(session
, &read_impl
);
1086 if (switch_channel_pre_answer(channel
) != SWITCH_STATUS_SUCCESS
) {
1087 return SWITCH_STATUS_FALSE
;
1090 if (switch_core_codec_init(&write_codec
,
1094 read_impl
.actual_samples_per_second
,
1095 read_impl
.microseconds_per_packet
/ 1000,
1096 read_impl
.number_of_channels
, SWITCH_CODEC_FLAG_ENCODE
| SWITCH_CODEC_FLAG_DECODE
,
1097 NULL
, switch_core_session_get_pool(session
)) != SWITCH_STATUS_SUCCESS
) {
1099 return SWITCH_STATUS_FALSE
;
1102 arg_recursion_check_start(args
);
1104 memset(&ts
, 0, sizeof(ts
));
1105 write_frame
.codec
= &write_codec
;
1106 write_frame
.data
= data
;
1107 write_frame
.buflen
= sizeof(data
);
1109 switch_buffer_create_dynamic(&audio_buffer
, 512, 1024, 0);
1110 teletone_init_session(&ts
, 0, teletone_handler
, audio_buffer
);
1111 ts
.rate
= read_impl
.actual_samples_per_second
;
1112 ts
.channels
= read_impl
.number_of_channels
;
1113 teletone_run(&ts
, script
);
1116 switch_buffer_set_loops(audio_buffer
, loops
);
1120 switch_status_t status
;
1122 if (!switch_channel_ready(channel
)) {
1126 if (switch_channel_test_flag(channel
, CF_BREAK
)) {
1127 switch_channel_clear_flag(channel
, CF_BREAK
);
1131 status
= switch_core_session_read_frame(session
, &read_frame
, SWITCH_IO_FLAG_NONE
, 0);
1133 if (!SWITCH_READ_ACCEPTABLE(status
)) {
1137 if (args
&& args
->dmachine
) {
1138 if ((status
= switch_ivr_dmachine_ping(args
->dmachine
, NULL
)) != SWITCH_STATUS_SUCCESS
) {
1143 if (args
&& (args
->read_frame_callback
)) {
1144 if ((status
= args
->read_frame_callback(session
, read_frame
, args
->user_data
)) != SWITCH_STATUS_SUCCESS
) {
1149 switch_ivr_parse_all_events(session
);
1153 dtmf handler function you can hook up to be executed when a digit is dialed during gentones
1154 if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
1156 if (switch_channel_has_dtmf(channel
)) {
1157 if (!args
->input_callback
&& !args
->buf
&& !args
->dmachine
) {
1160 switch_channel_dequeue_dtmf(channel
, &dtmf
);
1162 if (args
->dmachine
) {
1163 char ds
[2] = {dtmf
.digit
, '\0'};
1164 if ((status
= switch_ivr_dmachine_feed(args
->dmachine
, ds
, NULL
)) != SWITCH_STATUS_SUCCESS
) {
1169 if (args
->input_callback
) {
1170 status
= args
->input_callback(session
, (void *) &dtmf
, SWITCH_INPUT_TYPE_DTMF
, args
->buf
, args
->buflen
);
1171 } else if (args
->buf
) {
1172 *((char *) args
->buf
) = dtmf
.digit
;
1173 status
= SWITCH_STATUS_BREAK
;
1177 if (args
->input_callback
) {
1178 switch_event_t
*event
;
1180 if (switch_core_session_dequeue_event(session
, &event
, SWITCH_FALSE
) == SWITCH_STATUS_SUCCESS
) {
1181 switch_status_t ostatus
= args
->input_callback(session
, event
, SWITCH_INPUT_TYPE_EVENT
, args
->buf
, args
->buflen
);
1182 if (ostatus
!= SWITCH_STATUS_SUCCESS
) {
1185 switch_event_destroy(&event
);
1189 if (status
!= SWITCH_STATUS_SUCCESS
) {
1194 if ((write_frame
.datalen
= (uint32_t) switch_buffer_read_loop(audio_buffer
, write_frame
.data
, read_impl
.decoded_bytes_per_packet
)) <= 0) {
1198 write_frame
.samples
= write_frame
.datalen
/ 2;
1200 if (switch_core_session_write_frame(session
, &write_frame
, SWITCH_IO_FLAG_NONE
, 0) != SWITCH_STATUS_SUCCESS
) {
1205 switch_core_codec_destroy(&write_codec
);
1206 switch_buffer_destroy(&audio_buffer
);
1207 teletone_destroy_session(&ts
);
1209 arg_recursion_check_stop(args
);
1211 return SWITCH_STATUS_SUCCESS
;
1214 SWITCH_DECLARE(switch_status_t
) switch_ivr_get_file_handle(switch_core_session_t
*session
, switch_file_handle_t
**fh
)
1216 switch_file_handle_t
*fhp
;
1217 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
1220 switch_core_session_io_read_lock(session
);
1222 if ((fhp
= switch_channel_get_private(channel
, "__fh"))) {
1224 return SWITCH_STATUS_SUCCESS
;
1227 switch_core_session_io_rwunlock(session
);
1229 return SWITCH_STATUS_FALSE
;
1232 SWITCH_DECLARE(switch_status_t
) switch_ivr_release_file_handle(switch_core_session_t
*session
, switch_file_handle_t
**fh
)
1235 switch_core_session_io_rwunlock(session
);
1237 return SWITCH_STATUS_SUCCESS
;
1240 #define FILE_STARTSAMPLES 1024 * 32
1241 #define FILE_BLOCKSIZE 1024 * 8
1242 #define FILE_BUFSIZE 1024 * 64
1244 SWITCH_DECLARE(switch_status_t
) switch_ivr_play_file(switch_core_session_t
*session
, switch_file_handle_t
*fh
, const char *file
, switch_input_args_t
*args
)
1246 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
1247 int16_t *abuf
= NULL
;
1248 switch_dtmf_t dtmf
= { 0 };
1249 uint32_t interval
= 0, samples
= 0, framelen
, sample_start
= 0, channels
= 1;
1251 switch_size_t olen
= 0, llen
= 0;
1252 switch_frame_t write_frame
= { 0 };
1253 switch_timer_t timer
= { 0 };
1254 switch_codec_t codec
= { 0 };
1255 switch_memory_pool_t
*pool
= switch_core_session_get_pool(session
);
1257 switch_status_t status
= SWITCH_STATUS_SUCCESS
;
1258 switch_file_handle_t lfh
;
1260 //char *title = "", *copyright = "", *software = "", *artist = "", *comment = "", *date = "";
1262 char *backup_file
= NULL
;
1263 const char *backup_ext
;
1265 const char *timer_name
;
1267 const char *alt
= NULL
;
1268 const char *sleep_val
;
1269 const char *play_delimiter_val
;
1270 char play_delimiter
= 0;
1271 int sleep_val_i
= 250;
1273 switch_size_t bread
= 0;
1274 switch_codec_implementation_t read_impl
= { 0 };
1276 char *argv
[128] = { 0 };
1280 int timeout_samples
= 0;
1281 switch_bool_t timeout_as_success
= SWITCH_FALSE
;
1284 switch_event_t
*event
;
1285 uint32_t test_native
= 0, last_native
= 0;
1286 uint32_t buflen
= 0;
1289 int last_speed
= -1;
1291 if (switch_channel_pre_answer(channel
) != SWITCH_STATUS_SUCCESS
) {
1292 return SWITCH_STATUS_FALSE
;
1295 switch_core_session_get_read_impl(session
, &read_impl
);
1297 if ((var
= switch_channel_get_variable(channel
, "playback_timeout_sec_cumulative"))) {
1298 int tmp
= atoi(var
);
1300 timeout_samples
= read_impl
.actual_samples_per_second
* tmp
;
1304 } else if ((var
= switch_channel_get_variable(channel
, "playback_timeout_sec"))) {
1305 int tmp
= atoi(var
);
1307 timeout_samples
= read_impl
.actual_samples_per_second
* tmp
;
1311 if ((var
= switch_channel_get_variable(channel
, "playback_timeout_as_success"))) {
1312 if (switch_true(var
)) {
1313 timeout_as_success
= SWITCH_TRUE
;
1316 if ((play_delimiter_val
= switch_channel_get_variable(channel
, "playback_delimiter"))) {
1317 play_delimiter
= *play_delimiter_val
;
1319 if ((sleep_val
= switch_channel_get_variable(channel
, "playback_sleep_val"))) {
1320 int tmp
= atoi(sleep_val
);
1327 prefix
= switch_channel_get_variable(channel
, "sound_prefix");
1328 timer_name
= switch_channel_get_variable(channel
, "timer_name");
1330 if (zstr(file
) || !switch_channel_media_ready(channel
)) {
1331 return SWITCH_STATUS_FALSE
;
1334 arg_recursion_check_start(args
);
1336 if (play_delimiter
) {
1337 file_dup
= switch_core_session_strdup(session
, file
);
1338 argc
= switch_separate_string(file_dup
, play_delimiter
, argv
, (sizeof(argv
) / sizeof(argv
[0])));
1341 argv
[0] = (char *) file
;
1346 memset(fh
, 0, sizeof(lfh
));
1349 if (fh
->samples
> 0) {
1350 sample_start
= fh
->samples
;
1357 for (cur
= 0; switch_channel_ready(channel
) && !done
&& cur
< argc
; cur
++) {
1362 fh
->samples
= sample_start
= 0;
1364 status
= switch_ivr_sleep(session
, sleep_val_i
, SWITCH_FALSE
, args
);
1365 if(status
!= SWITCH_STATUS_SUCCESS
) {
1371 status
= SWITCH_STATUS_SUCCESS
;
1373 if (strchr(file
, ':')) {
1376 if (!strncasecmp(file
, "phrase:", 7)) {
1378 const char *lang
= switch_channel_get_variable(channel
, "language");
1380 dup
= switch_core_session_strdup(session
, alt
);
1383 if ((arg
= strchr(dup
, ':'))) {
1386 if ((status
= switch_ivr_phrase_macro(session
, dup
, arg
, lang
, args
)) != SWITCH_STATUS_SUCCESS
) {
1391 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Invalid Args\n");
1394 } else if (!strncasecmp(file
, "say:", 4)) {
1395 const char *engine
= NULL
, *voice
= NULL
, *text
= NULL
;
1399 engine
= switch_channel_get_variable(channel
, "tts_engine");
1400 voice
= switch_channel_get_variable(channel
, "tts_voice");
1402 if (engine
&& text
) {
1403 if ((status
= switch_ivr_speak_text(session
, engine
, voice
, (char *)text
, args
)) != SWITCH_STATUS_SUCCESS
) {
1407 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Invalid Args\n");
1416 prefix
= SWITCH_GLOBAL_dirs
.base_dir
;
1419 if (!strstr(file
, SWITCH_URL_SEPARATOR
)) {
1420 if (!switch_is_file_path(file
)) {
1425 tfile
= switch_core_session_strdup(session
, file
);
1427 while (*file
== '{') {
1428 if ((e
= switch_find_end_paren(tfile
, '{', '}'))) {
1431 while(*file
== ' ') file
++;
1439 file
= switch_core_session_sprintf(session
, "%s%s%s%s%s", switch_str_nil(tfile
), tfile
? "}" : "", prefix
, SWITCH_PATH_SEPARATOR
, file
);
1441 if ((ext
= strrchr(file
, '.'))) {
1445 if (!(backup_ext
= switch_channel_get_variable(channel
, "native_backup_extension"))) {
1449 ext
= read_impl
.iananame
;
1450 backup_file
= switch_core_session_sprintf(session
, "%s.%s", file
, backup_ext
);
1451 file
= switch_core_session_sprintf(session
, "%s.%s", file
, ext
);
1455 if ((prebuf
= switch_channel_get_variable(channel
, "stream_prebuffer"))) {
1456 int maybe
= atoi(prebuf
);
1464 fh
->prefix
= prefix
;
1467 flags
= SWITCH_FILE_FLAG_READ
| SWITCH_FILE_DATA_SHORT
;
1469 if (switch_channel_test_flag(channel
, CF_VIDEO
)) {
1470 flags
|= SWITCH_FILE_FLAG_VIDEO
;
1471 //switch_channel_set_flag_recursive(channel, CF_VIDEO_DECODED_READ);
1476 if (switch_core_file_open(fh
,
1478 read_impl
.number_of_channels
,
1479 read_impl
.actual_samples_per_second
, flags
, NULL
) == SWITCH_STATUS_SUCCESS
) {
1491 if (!switch_test_flag(fh
, SWITCH_FILE_OPEN
)) {
1492 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_FALSE
);
1493 status
= SWITCH_STATUS_NOTFOUND
;
1497 switch_channel_audio_sync(channel
);
1498 switch_core_session_io_write_lock(session
);
1499 switch_channel_set_private(channel
, "__fh", fh
);
1500 switch_core_session_io_rwunlock(session
);
1502 if (switch_core_file_has_video(fh
, SWITCH_TRUE
)) {
1503 switch_core_media_set_video_file(session
, fh
, SWITCH_RW_WRITE
);
1507 write_frame
.buflen
= FILE_STARTSAMPLES
* sizeof(*abuf
) * fh
->channels
;
1508 switch_zmalloc(abuf
, write_frame
.buflen
);
1509 write_frame
.data
= abuf
;
1512 if (sample_start
> 0) {
1514 switch_core_file_seek(fh
, &pos
, 0, SEEK_SET
);
1515 switch_core_file_seek(fh
, &pos
, sample_start
, SEEK_CUR
);
1516 switch_clear_flag_locked(fh
, SWITCH_FILE_SEEK
);
1519 if (switch_core_file_get_string(fh
, SWITCH_AUDIO_COL_STR_TITLE
, &p
) == SWITCH_STATUS_SUCCESS
) {
1520 //title = switch_core_session_strdup(session, p);
1521 switch_channel_set_variable(channel
, "RECORD_TITLE", p
);
1524 if (switch_core_file_get_string(fh
, SWITCH_AUDIO_COL_STR_COPYRIGHT
, &p
) == SWITCH_STATUS_SUCCESS
) {
1525 //copyright = switch_core_session_strdup(session, p);
1526 switch_channel_set_variable(channel
, "RECORD_COPYRIGHT", p
);
1529 if (switch_core_file_get_string(fh
, SWITCH_AUDIO_COL_STR_SOFTWARE
, &p
) == SWITCH_STATUS_SUCCESS
) {
1530 //software = switch_core_session_strdup(session, p);
1531 switch_channel_set_variable(channel
, "RECORD_SOFTWARE", p
);
1534 if (switch_core_file_get_string(fh
, SWITCH_AUDIO_COL_STR_ARTIST
, &p
) == SWITCH_STATUS_SUCCESS
) {
1535 //artist = switch_core_session_strdup(session, p);
1536 switch_channel_set_variable(channel
, "RECORD_ARTIST", p
);
1539 if (switch_core_file_get_string(fh
, SWITCH_AUDIO_COL_STR_COMMENT
, &p
) == SWITCH_STATUS_SUCCESS
) {
1540 //comment = switch_core_session_strdup(session, p);
1541 switch_channel_set_variable(channel
, "RECORD_COMMENT", p
);
1544 if (switch_core_file_get_string(fh
, SWITCH_AUDIO_COL_STR_DATE
, &p
) == SWITCH_STATUS_SUCCESS
) {
1545 //date = switch_core_session_strdup(session, p);
1546 switch_channel_set_variable(channel
, "RECORD_DATE", p
);
1549 interval
= read_impl
.microseconds_per_packet
/ 1000;
1553 if (!switch_core_codec_ready((&codec
))) {
1554 if (switch_core_codec_init(&codec
,
1559 interval
, read_impl
.number_of_channels
,
1560 SWITCH_CODEC_FLAG_ENCODE
| SWITCH_CODEC_FLAG_DECODE
, NULL
, pool
) == SWITCH_STATUS_SUCCESS
) {
1561 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
),
1562 SWITCH_LOG_DEBUG
, "Codec Activated %s@%uhz %u channels %dms\n",
1563 codec_name
, fh
->samplerate
, read_impl
.number_of_channels
, interval
);
1567 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
,
1568 "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name
,
1569 fh
->samplerate
, read_impl
.number_of_channels
, interval
);
1570 switch_core_session_io_write_lock(session
);
1571 switch_channel_set_private(channel
, "__fh", NULL
);
1572 switch_core_session_io_rwunlock(session
);
1574 switch_core_media_set_video_file(session
, NULL
, SWITCH_RW_WRITE
);
1576 switch_core_file_close(fh
);
1578 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_FALSE
);
1579 status
= SWITCH_STATUS_GENERR
;
1584 test_native
= switch_test_flag(fh
, SWITCH_FILE_NATIVE
);
1587 write_frame
.codec
= switch_core_session_get_read_codec(session
);
1588 samples
= read_impl
.samples_per_packet
;
1589 framelen
= read_impl
.encoded_bytes_per_packet
;
1590 channels
= read_impl
.number_of_channels
;
1591 if (framelen
== 0) {
1592 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "%s cannot play or record native files with variable length data\n", switch_channel_get_name(channel
));
1594 switch_core_session_io_write_lock(session
);
1595 switch_channel_set_private(channel
, "__fh", NULL
);
1596 switch_core_session_io_rwunlock(session
);
1598 switch_core_media_set_video_file(session
, NULL
, SWITCH_RW_WRITE
);
1599 switch_core_file_close(fh
);
1601 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_FALSE
);
1602 status
= SWITCH_STATUS_GENERR
;
1607 write_frame
.codec
= &codec
;
1608 samples
= codec
.implementation
->samples_per_packet
;
1609 framelen
= codec
.implementation
->decoded_bytes_per_packet
;
1610 channels
= codec
.implementation
->number_of_channels
;
1613 last_native
= test_native
;
1615 if (timer_name
&& !timer
.samplecount
) {
1618 len
= samples
* 2 * channels
;
1619 if (switch_core_timer_init(&timer
, timer_name
, interval
, samples
, pool
) != SWITCH_STATUS_SUCCESS
) {
1620 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Setup timer failed!\n");
1621 switch_core_codec_destroy(&codec
);
1622 switch_core_session_io_write_lock(session
);
1623 switch_channel_set_private(channel
, "__fh", NULL
);
1624 switch_core_session_io_rwunlock(session
);
1626 switch_core_media_set_video_file(session
, NULL
, SWITCH_RW_WRITE
);
1628 switch_core_file_close(fh
);
1629 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_FALSE
);
1630 status
= SWITCH_STATUS_GENERR
;
1633 switch_core_timer_sync(&timer
); // Sync timer
1634 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
,
1635 "Setup timer success %u bytes per %d ms! %d ch\n", len
, interval
, codec
.implementation
->number_of_channels
);
1637 write_frame
.rate
= fh
->samplerate
;
1638 write_frame
.channels
= fh
->channels
;
1640 /* start a thread to absorb incoming audio */
1641 switch_core_service_session(session
);
1644 ilen
= samples
* channels
;
1646 if (switch_event_create(&event
, SWITCH_EVENT_PLAYBACK_START
) == SWITCH_STATUS_SUCCESS
) {
1647 switch_channel_event_set_data(channel
, event
);
1648 if (!strncasecmp(file
, "local_stream:", 13)) {
1649 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "Playback-File-Type", "local_stream");
1651 if (!strncasecmp(file
, "tone_stream:", 12)) {
1652 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "Playback-File-Type", "tone_stream");
1654 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "Playback-File-Path", file
);
1656 switch_event_merge(event
, fh
->params
);
1658 switch_event_fire(&event
);
1661 if (!fh
->audio_buffer
) {
1662 switch_buffer_create_dynamic(&fh
->audio_buffer
, FILE_BLOCKSIZE
, FILE_BUFSIZE
, 0);
1663 switch_assert(fh
->audio_buffer
);
1670 if (!switch_channel_ready(channel
)) {
1671 status
= SWITCH_STATUS_FALSE
;
1675 if ((f
= switch_channel_test_flag(channel
, CF_BREAK
))) {
1676 switch_channel_clear_flag(channel
, CF_BREAK
);
1680 status
= SWITCH_STATUS_BREAK
;
1684 switch_ivr_parse_all_events(session
);
1688 dtmf handler function you can hook up to be executed when a digit is dialed during playback
1689 if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
1691 if (switch_channel_has_dtmf(channel
)) {
1692 switch_channel_dequeue_dtmf(channel
, &dtmf
);
1694 if (!args
->input_callback
&& !args
->buf
&& !args
->dmachine
) {
1695 status
= SWITCH_STATUS_BREAK
;
1701 if (args
->dmachine
) {
1702 char ds
[2] = {dtmf
.digit
, '\0'};
1703 if ((status
= switch_ivr_dmachine_feed(args
->dmachine
, ds
, NULL
)) != SWITCH_STATUS_SUCCESS
) {
1708 if (args
->input_callback
) {
1709 status
= args
->input_callback(session
, (void *) &dtmf
, SWITCH_INPUT_TYPE_DTMF
, args
->buf
, args
->buflen
);
1710 } else if (args
->buf
) {
1711 *((char *) args
->buf
) = dtmf
.digit
;
1712 status
= SWITCH_STATUS_BREAK
;
1716 if (args
->input_callback
) {
1717 switch_event_t
*event
;
1719 if (switch_core_session_dequeue_event(session
, &event
, SWITCH_FALSE
) == SWITCH_STATUS_SUCCESS
) {
1720 switch_status_t ostatus
= args
->input_callback(session
, event
, SWITCH_INPUT_TYPE_EVENT
, args
->buf
, args
->buflen
);
1721 if (ostatus
!= SWITCH_STATUS_SUCCESS
) {
1725 switch_event_destroy(&event
);
1729 if (status
!= SWITCH_STATUS_SUCCESS
) {
1735 buflen
= FILE_STARTSAMPLES
* sizeof(*abuf
) * (fh
->cur_channels
> 0 ? fh
->cur_channels
: fh
->channels
);
1737 if (buflen
> write_frame
.buflen
) {
1738 abuf
= realloc(abuf
, buflen
);
1739 write_frame
.data
= abuf
;
1740 write_frame
.buflen
= buflen
;
1743 if (switch_test_flag(fh
, SWITCH_FILE_PAUSE
)) {
1744 if (framelen
> FILE_STARTSAMPLES
) {
1745 framelen
= FILE_STARTSAMPLES
;
1747 memset(abuf
, 255, framelen
);
1750 } else if (fh
->sp_audio_buffer
&& (eof
|| (switch_buffer_inuse(fh
->sp_audio_buffer
) > (switch_size_t
) (framelen
)))) {
1751 if (!(bread
= switch_buffer_read(fh
->sp_audio_buffer
, abuf
, framelen
))) {
1759 if (bread
< framelen
) {
1760 memset(abuf
+ bread
, 255, framelen
- bread
);
1763 olen
= switch_test_flag(fh
, SWITCH_FILE_NATIVE
) ? framelen
: ilen
;
1765 } else if (fh
->audio_buffer
&& (eof
|| (switch_buffer_inuse(fh
->audio_buffer
) > (switch_size_t
) (framelen
)))) {
1766 if (!(bread
= switch_buffer_read(fh
->audio_buffer
, abuf
, framelen
))) {
1774 fh
->offset_pos
+= (uint32_t)(switch_test_flag(fh
, SWITCH_FILE_NATIVE
) ? bread
: bread
/ 2);
1776 if (bread
< framelen
) {
1777 memset(abuf
+ bread
, 255, framelen
- bread
);
1780 olen
= switch_test_flag(fh
, SWITCH_FILE_NATIVE
) ? framelen
: ilen
;
1782 switch_status_t rstatus
;
1787 olen
= FILE_STARTSAMPLES
;
1788 if (!switch_test_flag(fh
, SWITCH_FILE_NATIVE
)) {
1791 switch_set_flag_locked(fh
, SWITCH_FILE_BREAK_ON_CHANGE
);
1793 if ((rstatus
= switch_core_file_read(fh
, abuf
, &olen
)) == SWITCH_STATUS_BREAK
) {
1797 if (rstatus
!= SWITCH_STATUS_SUCCESS
) {
1802 test_native
= switch_test_flag(fh
, SWITCH_FILE_NATIVE
);
1804 if (test_native
!= last_native
) {
1806 write_frame
.codec
= switch_core_session_get_read_codec(session
);
1807 framelen
= read_impl
.encoded_bytes_per_packet
;
1808 if (framelen
== 0) {
1809 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "%s cannot play or record native files with variable length data\n", switch_channel_get_name(channel
));
1814 write_frame
.codec
= &codec
;
1815 framelen
= codec
.implementation
->decoded_bytes_per_packet
;
1817 switch_buffer_zero(fh
->audio_buffer
);
1820 last_native
= test_native
;
1822 switch_buffer_write(fh
->audio_buffer
, abuf
, switch_test_flag(fh
, SWITCH_FILE_NATIVE
) ? olen
: olen
* 2 * fh
->channels
);
1823 olen
= switch_buffer_read(fh
->audio_buffer
, abuf
, framelen
);
1824 fh
->offset_pos
+= (uint32_t)(olen
/ 2);
1826 if (!switch_test_flag(fh
, SWITCH_FILE_NATIVE
)) {
1832 if (done
|| olen
<= 0) {
1836 if (!switch_test_flag(fh
, SWITCH_FILE_NATIVE
)) {
1837 if (fh
->speed
> 2) {
1839 } else if (fh
->speed
< -2) {
1844 if (!switch_test_flag(fh
, SWITCH_FILE_NATIVE
) && fh
->audio_buffer
&& last_speed
> -1 && last_speed
!= fh
->speed
) {
1845 switch_buffer_zero(fh
->sp_audio_buffer
);
1848 if (switch_test_flag(fh
, SWITCH_FILE_SEEK
)) {
1849 /* file position has changed flush the buffer */
1850 switch_buffer_zero(fh
->audio_buffer
);
1851 switch_clear_flag_locked(fh
, SWITCH_FILE_SEEK
);
1855 if (!switch_test_flag(fh
, SWITCH_FILE_NATIVE
) && fh
->speed
&& do_speed
) {
1856 float factor
= 0.25f
* abs(fh
->speed
);
1857 switch_size_t newlen
, supplement
, step
;
1858 short *bp
= write_frame
.data
;
1859 switch_size_t wrote
= 0;
1861 supplement
= (int) (factor
* olen
);
1865 newlen
= (fh
->speed
> 0) ? olen
- supplement
: olen
+ supplement
;
1867 step
= (fh
->speed
> 0) ? (newlen
/ supplement
) : (olen
/ supplement
);
1869 if (!fh
->sp_audio_buffer
) {
1870 switch_buffer_create_dynamic(&fh
->sp_audio_buffer
, 1024, 1024, 0);
1873 while ((wrote
+ step
) < newlen
) {
1874 switch_buffer_write(fh
->sp_audio_buffer
, bp
, step
* 2);
1877 if (fh
->speed
> 0) {
1882 f
= (float) (*bp
+ *(bp
+ 1) + *(bp
- 1));
1885 switch_buffer_write(fh
->sp_audio_buffer
, &s
, 2);
1889 if (wrote
< newlen
) {
1890 switch_size_t r
= newlen
- wrote
;
1891 switch_buffer_write(fh
->sp_audio_buffer
, bp
, r
* 2);
1893 last_speed
= fh
->speed
;
1898 uint8_t *dp
= (uint8_t *) write_frame
.data
;
1899 memset(dp
+ (int) olen
, 255, (int) (llen
- olen
));
1905 if (switch_core_timer_next(&timer
) != SWITCH_STATUS_SUCCESS
) {
1908 } else { /* time off the channel (if you must) */
1909 switch_frame_t
*read_frame
;
1910 switch_status_t tstatus
;
1912 while (switch_channel_ready(channel
) && switch_channel_test_flag(channel
, CF_HOLD
)) {
1913 switch_ivr_parse_all_messages(session
);
1914 switch_yield(10000);
1917 tstatus
= switch_core_session_read_frame(session
, &read_frame
, SWITCH_IO_FLAG_SINGLE_READ
, 0);
1920 if (!SWITCH_READ_ACCEPTABLE(tstatus
)) {
1924 if (args
&& args
->dmachine
) {
1925 if ((status
= switch_ivr_dmachine_ping(args
->dmachine
, NULL
)) != SWITCH_STATUS_SUCCESS
) {
1930 if (args
&& (args
->read_frame_callback
)) {
1932 switch_set_flag_locked(fh
, SWITCH_FILE_CALLBACK
);
1933 if ((status
= args
->read_frame_callback(session
, read_frame
, args
->user_data
)) != SWITCH_STATUS_SUCCESS
) {
1936 switch_clear_flag_locked(fh
, SWITCH_FILE_CALLBACK
);
1945 write_frame
.samples
= (uint32_t) olen
;
1947 if (switch_test_flag(fh
, SWITCH_FILE_NATIVE
)) {
1948 write_frame
.datalen
= (uint32_t) olen
;
1950 write_frame
.datalen
= write_frame
.samples
* 2;
1956 write_frame
.timestamp
= timer
.samplecount
;
1959 #if SWITCH_BYTE_ORDER == __BIG_ENDIAN
1960 if (!switch_test_flag(fh
, SWITCH_FILE_NATIVE
) && l16
) {
1961 switch_swap_linear(write_frame
.data
, (int) write_frame
.datalen
/ 2);
1965 if (!switch_test_flag(fh
, SWITCH_FILE_NATIVE
)) {
1966 if (fh
->volgranular
) {
1967 switch_change_sln_volume_granular(write_frame
.data
, write_frame
.datalen
/ 2, fh
->volgranular
);
1968 } else if (fh
->vol
) { /* deprecated 2022-Q1 */
1969 switch_change_sln_volume(write_frame
.data
, write_frame
.datalen
/ 2, fh
->vol
);
1973 /* write silence while dmachine is in reading state */
1974 if (args
&& args
->dmachine
&& switch_ivr_dmachine_is_parsing(args
->dmachine
)) {
1975 memset(write_frame
.data
, 0, write_frame
.datalen
);
1978 status
= switch_core_session_write_frame(session
, &write_frame
, SWITCH_IO_FLAG_NONE
, 0);
1980 if (timeout_samples
) {
1981 timeout_samples
-= write_frame
.samples
;
1982 if (timeout_samples
<= 0) {
1983 timeout_samples
= 0;
1984 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "timeout reached playing file\n");
1985 if (timeout_as_success
) {
1986 status
= SWITCH_STATUS_SUCCESS
;
1988 status
= SWITCH_STATUS_TIMEOUT
;
1996 if (status
== SWITCH_STATUS_MORE_DATA
) {
1997 status
= SWITCH_STATUS_SUCCESS
;
2000 } else if (status
!= SWITCH_STATUS_SUCCESS
) {
2010 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "done playing file %s\n", file
);
2011 switch_channel_set_variable_printf(channel
, "playback_last_offset_pos", "%d", fh
->offset_pos
);
2013 if (read_impl
.samples_per_second
&& fh
->native_rate
>= 1000) {
2014 switch_channel_set_variable_printf(channel
, "playback_seconds", "%d", fh
->samples_in
/ fh
->native_rate
);
2015 switch_channel_set_variable_printf(channel
, "playback_ms", "%d", fh
->samples_in
/ (fh
->native_rate
/ 1000));
2018 switch_channel_set_variable_printf(channel
, "playback_samples", "%d", fh
->samples_in
);
2020 if (switch_event_create(&event
, SWITCH_EVENT_PLAYBACK_STOP
) == SWITCH_STATUS_SUCCESS
) {
2021 switch_channel_event_set_data(channel
, event
);
2022 if (!strncasecmp(file
, "local_stream:", 13)) {
2023 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "Playback-File-Type", "local_stream");
2025 if (!strncasecmp(file
, "tone_stream:", 12)) {
2026 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "Playback-File-Type", "tone_stream");
2028 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "Playback-File-Path", file
);
2029 if (status
== SWITCH_STATUS_BREAK
) {
2030 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "Playback-Status", "break");
2032 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "Playback-Status", "done");
2035 switch_event_merge(event
, fh
->params
);
2037 switch_event_fire(&event
);
2040 switch_core_session_io_write_lock(session
);
2041 switch_channel_set_private(channel
, "__fh", NULL
);
2042 switch_core_session_io_rwunlock(session
);
2044 switch_core_media_set_video_file(session
, NULL
, SWITCH_RW_WRITE
);
2045 switch_core_file_close(fh
);
2047 if (fh
->audio_buffer
) {
2048 switch_buffer_destroy(&fh
->audio_buffer
);
2051 if (fh
->sp_audio_buffer
) {
2052 switch_buffer_destroy(&fh
->sp_audio_buffer
);
2056 if (switch_core_codec_ready((&codec
))) {
2057 switch_core_codec_destroy(&codec
);
2060 if (timer
.samplecount
) {
2061 /* End the audio absorbing thread */
2062 switch_core_thread_session_end(session
);
2063 switch_core_timer_destroy(&timer
);
2066 switch_safe_free(abuf
);
2068 switch_core_session_reset(session
, SWITCH_FALSE
, SWITCH_FALSE
);
2070 arg_recursion_check_stop(args
);
2072 if (timeout_samples
&& cumulative
) {
2073 switch_channel_set_variable_printf(channel
, "playback_timeout_sec_cumulative", "%d", timeout_samples
/ read_impl
.actual_samples_per_second
);
2080 SWITCH_DECLARE(switch_status_t
) switch_ivr_wait_for_silence(switch_core_session_t
*session
, uint32_t thresh
,
2081 uint32_t silence_hits
, uint32_t listen_hits
, uint32_t timeout_ms
, const char *file
)
2083 uint32_t score
, count
= 0, j
= 0;
2085 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
2087 uint32_t org_silence_hits
= silence_hits
;
2089 switch_frame_t
*read_frame
;
2090 switch_status_t status
= SWITCH_STATUS_FALSE
;
2092 uint32_t listening
= 0;
2094 switch_codec_t raw_codec
= { 0 };
2095 int16_t *abuf
= NULL
;
2096 switch_frame_t write_frame
= { 0 };
2097 switch_file_handle_t fh
= { 0 };
2098 int32_t sample_count
= 0;
2099 switch_codec_implementation_t read_impl
= { 0 };
2100 switch_core_session_get_read_impl(session
, &read_impl
);
2104 sample_count
= (read_impl
.actual_samples_per_second
/ 1000) * timeout_ms
;
2108 if (switch_core_file_open(&fh
,
2110 read_impl
.number_of_channels
,
2111 read_impl
.actual_samples_per_second
, SWITCH_FILE_FLAG_READ
| SWITCH_FILE_DATA_SHORT
, NULL
) != SWITCH_STATUS_SUCCESS
) {
2112 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failure opening playback file %s.\n", file
);
2113 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_FALSE
);
2114 return SWITCH_STATUS_NOTFOUND
;
2116 switch_zmalloc(abuf
, SWITCH_RECOMMENDED_BUFFER_SIZE
);
2117 write_frame
.data
= abuf
;
2118 write_frame
.buflen
= SWITCH_RECOMMENDED_BUFFER_SIZE
;
2122 if (switch_core_codec_init(&raw_codec
,
2126 read_impl
.actual_samples_per_second
,
2127 read_impl
.microseconds_per_packet
/ 1000,
2128 1, SWITCH_CODEC_FLAG_ENCODE
| SWITCH_CODEC_FLAG_DECODE
,
2129 NULL
, switch_core_session_get_pool(session
)) != SWITCH_STATUS_SUCCESS
) {
2131 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failed to initialize L16 codec.\n");
2132 status
= SWITCH_STATUS_FALSE
;
2136 write_frame
.codec
= &raw_codec
;
2138 divisor
= read_impl
.actual_samples_per_second
/ 8000;
2139 channels
= read_impl
.number_of_channels
;
2141 switch_core_session_set_read_codec(session
, &raw_codec
);
2143 while (switch_channel_ready(channel
)) {
2145 /* reinitialize energy value per loop */
2148 status
= switch_core_session_read_frame(session
, &read_frame
, SWITCH_IO_FLAG_NONE
, 0);
2150 if (!SWITCH_READ_ACCEPTABLE(status
)) {
2151 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failed to read frame.\n");
2156 sample_count
-= raw_codec
.implementation
->samples_per_packet
;
2157 if (sample_count
<= 0) {
2158 switch_channel_set_variable(channel
, "wait_for_silence_timeout", "true");
2159 switch_channel_set_variable_printf(channel
, "wait_for_silence_listenhits", "%d", listening
);
2160 switch_channel_set_variable_printf(channel
, "wait_for_silence_silence_hits", "%d", silence_hits
);
2161 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
,
2162 "switch_ivr_wait_for_silence: TIMEOUT after %d ms at %d listen hits, %d silence hits, %d countdown\n",
2163 timeout_ms
, listening
, (org_silence_hits
- silence_hits
), countdown
);
2169 switch_size_t olen
= raw_codec
.implementation
->samples_per_packet
;
2171 if (switch_core_file_read(&fh
, abuf
, &olen
) != SWITCH_STATUS_SUCCESS
) {
2172 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failed to read file %s.\n", file
);
2176 write_frame
.samples
= (uint32_t) olen
;
2177 write_frame
.datalen
= (uint32_t) (olen
* sizeof(int16_t) * fh
.channels
);
2178 if ((status
= switch_core_session_write_frame(session
, &write_frame
, SWITCH_IO_FLAG_NONE
, 0)) != SWITCH_STATUS_SUCCESS
) {
2179 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failed to write frame from file %s.\n", file
);
2186 switch_channel_set_variable(channel
, "wait_for_silence_timeout", "false");
2187 switch_channel_set_variable_printf(channel
, "wait_for_silence_listenhits", "%d", listening
);
2188 switch_channel_set_variable_printf(channel
, "wait_for_silence_silence_hits", "%d", silence_hits
);
2189 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "switch_ivr_wait_for_silence: SILENCE DETECTED\n");
2196 data
= (int16_t *) read_frame
->data
;
2198 /* Need to check if the read_frame is valid before attempting to get "energy" value from it */
2199 if (read_frame
->seq
) {
2200 for (energy
= 0, j
= 0, count
= 0; count
< read_frame
->samples
; count
++) {
2201 energy
+= abs(data
[j
++]);
2206 score
= (uint32_t) (energy
/ (read_frame
->samples
/ divisor
));
2208 if (score
>= thresh
) {
2212 if (((listen_hits
== 0) || (listening
> listen_hits
)) && (score
< thresh
)) {
2213 if (!--silence_hits
) {
2217 silence_hits
= org_silence_hits
;
2221 switch_core_session_reset(session
, SWITCH_FALSE
, SWITCH_TRUE
);
2222 switch_core_codec_destroy(&raw_codec
);
2228 switch_core_file_close(&fh
);
2235 SWITCH_DECLARE(switch_status_t
) switch_ivr_detect_audio(switch_core_session_t
*session
, uint32_t thresh
,
2236 uint32_t audio_hits
, uint32_t timeout_ms
, const char *file
)
2238 uint32_t score
, count
= 0, j
= 0;
2240 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
2243 switch_frame_t
*read_frame
;
2244 switch_status_t status
= SWITCH_STATUS_FALSE
;
2247 switch_codec_t raw_codec
= { 0 };
2248 int16_t *abuf
= NULL
;
2249 switch_frame_t write_frame
= { 0 };
2250 switch_file_handle_t fh
= { 0 };
2251 int32_t sample_count
= 0;
2252 switch_codec_implementation_t read_impl
= { 0 };
2253 switch_core_session_get_read_impl(session
, &read_impl
);
2256 sample_count
= (read_impl
.actual_samples_per_second
/ 1000) * timeout_ms
;
2260 if (switch_core_file_open(&fh
,
2262 read_impl
.number_of_channels
,
2263 read_impl
.actual_samples_per_second
, SWITCH_FILE_FLAG_READ
| SWITCH_FILE_DATA_SHORT
, NULL
) != SWITCH_STATUS_SUCCESS
) {
2264 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failure opening playback file %s.\n", file
);
2265 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_FALSE
);
2266 return SWITCH_STATUS_NOTFOUND
;
2268 switch_zmalloc(abuf
, SWITCH_RECOMMENDED_BUFFER_SIZE
);
2269 write_frame
.data
= abuf
;
2270 write_frame
.buflen
= SWITCH_RECOMMENDED_BUFFER_SIZE
;
2274 if (switch_core_codec_init(&raw_codec
,
2278 read_impl
.actual_samples_per_second
,
2279 read_impl
.microseconds_per_packet
/ 1000,
2280 1, SWITCH_CODEC_FLAG_ENCODE
| SWITCH_CODEC_FLAG_DECODE
,
2281 NULL
, switch_core_session_get_pool(session
)) != SWITCH_STATUS_SUCCESS
) {
2283 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failed to initialize L16 codec.\n");
2284 status
= SWITCH_STATUS_FALSE
;
2288 write_frame
.codec
= &raw_codec
;
2290 divisor
= read_impl
.actual_samples_per_second
/ 8000;
2291 channels
= read_impl
.number_of_channels
;
2293 switch_core_session_set_read_codec(session
, &raw_codec
);
2295 while (switch_channel_ready(channel
)) {
2297 status
= switch_core_session_read_frame(session
, &read_frame
, SWITCH_IO_FLAG_NONE
, 0);
2299 if (!SWITCH_READ_ACCEPTABLE(status
)) {
2300 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failed to read frame.\n");
2305 sample_count
-= raw_codec
.implementation
->samples_per_packet
;
2306 if (sample_count
<= 0) {
2307 switch_channel_set_variable(channel
, "detect_audio_timeout", "true");
2308 switch_channel_set_variable_printf(channel
, "detect_audio_hits", "%d", hits
);
2309 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
,
2310 "switch_ivr_detect_audio: TIMEOUT after %d ms at %d hits\n",
2317 switch_size_t olen
= raw_codec
.implementation
->samples_per_packet
;
2319 if (switch_core_file_read(&fh
, abuf
, &olen
) != SWITCH_STATUS_SUCCESS
) {
2320 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failed to read file %s.\n", file
);
2324 write_frame
.samples
= (uint32_t) olen
;
2325 write_frame
.datalen
= (uint32_t) (olen
* sizeof(int16_t) * fh
.channels
);
2326 if ((status
= switch_core_session_write_frame(session
, &write_frame
, SWITCH_IO_FLAG_NONE
, 0)) != SWITCH_STATUS_SUCCESS
) {
2327 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failed to write frame from file %s.\n", file
);
2332 data
= (int16_t *) read_frame
->data
;
2334 for (energy
= 0, j
= 0, count
= 0; count
< read_frame
->samples
; count
++) {
2335 energy
+= abs(data
[j
++]);
2339 score
= (uint32_t) (energy
/ (read_frame
->samples
/ divisor
));
2341 if (score
>= thresh
) {
2347 if (hits
> audio_hits
) {
2348 switch_channel_set_variable(channel
, "detect_audio_timeout", "false");
2349 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "switch_ivr_detect_audio: AUDIO DETECTED\n");
2354 switch_core_session_reset(session
, SWITCH_FALSE
, SWITCH_TRUE
);
2355 switch_core_codec_destroy(&raw_codec
);
2361 switch_core_file_close(&fh
);
2368 SWITCH_DECLARE(switch_status_t
) switch_ivr_detect_silence(switch_core_session_t
*session
, uint32_t thresh
,
2369 uint32_t silence_hits
, uint32_t timeout_ms
, const char *file
)
2371 uint32_t score
, count
= 0, j
= 0;
2373 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
2376 switch_frame_t
*read_frame
;
2377 switch_status_t status
= SWITCH_STATUS_FALSE
;
2380 switch_codec_t raw_codec
= { 0 };
2381 int16_t *abuf
= NULL
;
2382 switch_frame_t write_frame
= { 0 };
2383 switch_file_handle_t fh
= { 0 };
2384 int32_t sample_count
= 0;
2385 switch_codec_implementation_t read_impl
= { 0 };
2386 switch_core_session_get_read_impl(session
, &read_impl
);
2390 sample_count
= (read_impl
.actual_samples_per_second
/ 1000) * timeout_ms
;
2394 if (switch_core_file_open(&fh
,
2396 read_impl
.number_of_channels
,
2397 read_impl
.actual_samples_per_second
, SWITCH_FILE_FLAG_READ
| SWITCH_FILE_DATA_SHORT
, NULL
) != SWITCH_STATUS_SUCCESS
) {
2398 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failure opening playback file %s.\n", file
);
2399 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_FALSE
);
2400 return SWITCH_STATUS_NOTFOUND
;
2402 switch_zmalloc(abuf
, SWITCH_RECOMMENDED_BUFFER_SIZE
);
2403 write_frame
.data
= abuf
;
2404 write_frame
.buflen
= SWITCH_RECOMMENDED_BUFFER_SIZE
;
2408 if (switch_core_codec_init(&raw_codec
,
2412 read_impl
.actual_samples_per_second
,
2413 read_impl
.microseconds_per_packet
/ 1000,
2414 1, SWITCH_CODEC_FLAG_ENCODE
| SWITCH_CODEC_FLAG_DECODE
,
2415 NULL
, switch_core_session_get_pool(session
)) != SWITCH_STATUS_SUCCESS
) {
2417 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failed to initialize L16 codec.\n");
2418 status
= SWITCH_STATUS_FALSE
;
2422 write_frame
.codec
= &raw_codec
;
2424 divisor
= read_impl
.actual_samples_per_second
/ 8000;
2425 channels
= read_impl
.number_of_channels
;
2427 switch_core_session_set_read_codec(session
, &raw_codec
);
2429 while (switch_channel_ready(channel
)) {
2431 status
= switch_core_session_read_frame(session
, &read_frame
, SWITCH_IO_FLAG_NONE
, 0);
2433 if (!SWITCH_READ_ACCEPTABLE(status
)) {
2434 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failed to read frame.\n");
2439 sample_count
-= raw_codec
.implementation
->samples_per_packet
;
2440 if (sample_count
<= 0) {
2441 switch_channel_set_variable(channel
, "detect_silence_timeout", "true");
2442 switch_channel_set_variable_printf(channel
, "detect_silence_hits", "%d", hits
);
2443 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
,
2444 "switch_ivr_detect_silence: TIMEOUT after %d ms at %d hits\n",
2451 switch_size_t olen
= raw_codec
.implementation
->samples_per_packet
;
2453 if (switch_core_file_read(&fh
, abuf
, &olen
) != SWITCH_STATUS_SUCCESS
) {
2454 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failed to read file %s.\n", file
);
2458 write_frame
.samples
= (uint32_t) olen
;
2459 write_frame
.datalen
= (uint32_t) (olen
* sizeof(int16_t) * fh
.channels
);
2460 if ((status
= switch_core_session_write_frame(session
, &write_frame
, SWITCH_IO_FLAG_NONE
, 0)) != SWITCH_STATUS_SUCCESS
) {
2461 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Failed to write frame from file %s.\n", file
);
2466 data
= (int16_t *) read_frame
->data
;
2468 for (energy
= 0, j
= 0, count
= 0; count
< read_frame
->samples
; count
++) {
2469 energy
+= abs(data
[j
++]);
2473 score
= (uint32_t) (energy
/ (read_frame
->samples
/ divisor
));
2475 if (score
<= thresh
) {
2481 if (hits
> silence_hits
) {
2482 switch_channel_set_variable(channel
, "detect_silence_timeout", "false");
2483 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "switch_ivr_detect_silence: SILENCE DETECTED\n");
2488 switch_core_session_reset(session
, SWITCH_FALSE
, SWITCH_TRUE
);
2489 switch_core_codec_destroy(&raw_codec
);
2495 switch_core_file_close(&fh
);
2502 SWITCH_DECLARE(switch_status_t
) switch_ivr_read(switch_core_session_t
*session
,
2503 uint32_t min_digits
,
2504 uint32_t max_digits
,
2505 const char *prompt_audio_file
,
2506 const char *var_name
,
2508 switch_size_t digit_buffer_length
,
2510 const char *valid_terminators
,
2511 uint32_t digit_timeout
)
2514 switch_channel_t
*channel
;
2515 switch_input_args_t args
= { 0 };
2516 switch_status_t status
= SWITCH_STATUS_SUCCESS
;
2519 int term_required
= 0;
2522 if (valid_terminators
&& *valid_terminators
== '=') {
2526 switch_assert(session
);
2528 if (!digit_timeout
) {
2529 digit_timeout
= timeout
;
2532 if (max_digits
< min_digits
) {
2533 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
,
2534 "Max digits %u is less than Min %u, forcing Max to %u\n", max_digits
, min_digits
, min_digits
);
2535 max_digits
= min_digits
;
2538 channel
= switch_core_session_get_channel(session
);
2539 switch_channel_set_variable(channel
, SWITCH_READ_RESULT_VARIABLE
, NULL
);
2542 switch_channel_set_variable(channel
, var_name
, NULL
);
2545 if ((min_digits
&& digit_buffer_length
< min_digits
) || digit_buffer_length
< max_digits
) {
2546 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Buffer too small!\n");
2547 return SWITCH_STATUS_FALSE
;
2550 if (switch_channel_pre_answer(channel
) != SWITCH_STATUS_SUCCESS
) {
2551 return SWITCH_STATUS_FALSE
;
2554 memset(digit_buffer
, 0, digit_buffer_length
);
2555 args
.buf
= digit_buffer
;
2556 args
.buflen
= (uint32_t) digit_buffer_length
;
2558 if (!zstr(prompt_audio_file
) && strcasecmp(prompt_audio_file
, "silence")) {
2559 if ((status
= switch_ivr_play_file(session
, NULL
, prompt_audio_file
, &args
)) == SWITCH_STATUS_BREAK
) {
2560 status
= SWITCH_STATUS_SUCCESS
;
2564 if (status
!= SWITCH_STATUS_SUCCESS
&& status
!= SWITCH_STATUS_BREAK
) {
2568 len
= strlen(digit_buffer
);
2570 if ((min_digits
&& len
< min_digits
) || len
< max_digits
) {
2571 args
.buf
= digit_buffer
+ len
;
2572 args
.buflen
= (uint32_t) (digit_buffer_length
- len
);
2573 status
= switch_ivr_collect_digits_count(session
, digit_buffer
, digit_buffer_length
, max_digits
, valid_terminators
, &tb
[0],
2574 len
? digit_timeout
: timeout
, digit_timeout
, 0);
2581 switch_channel_set_variable(channel
, SWITCH_READ_TERMINATOR_USED_VARIABLE
, tb
);
2583 if (!zstr(valid_terminators
) && (p
= strchr(valid_terminators
, tb
[0]))) {
2584 if (p
>= (valid_terminators
+ 1) && (*(p
- 1) == '+' || *(p
- 1) == 'x')) {
2585 switch_snprintf(digit_buffer
+ strlen(digit_buffer
), digit_buffer_length
- strlen(digit_buffer
), "%s", tb
);
2586 if (*(p
- 1) == 'x') {
2587 status
= SWITCH_STATUS_RESTART
;
2591 } else if (term_required
) {
2592 status
= SWITCH_STATUS_TOO_SMALL
;
2595 len
= strlen(digit_buffer
);
2596 if ((min_digits
&& len
< min_digits
)) {
2597 status
= SWITCH_STATUS_TOO_SMALL
;
2601 case SWITCH_STATUS_SUCCESS
:
2602 switch_channel_set_variable(channel
, SWITCH_READ_RESULT_VARIABLE
, "success");
2604 case SWITCH_STATUS_TIMEOUT
:
2605 switch_channel_set_variable(channel
, SWITCH_READ_RESULT_VARIABLE
, "timeout");
2608 switch_channel_set_variable(channel
, SWITCH_READ_RESULT_VARIABLE
, "failure");
2615 if (status
!= SWITCH_STATUS_RESTART
&& max_digits
== 1 && len
== 1 && valid_terminators
&& strchr(valid_terminators
, *digit_buffer
)) {
2616 *digit_buffer
= '\0';
2619 if (var_name
&& !zstr(digit_buffer
)) {
2620 switch_channel_set_variable(channel
, var_name
, digit_buffer
);
2627 SWITCH_DECLARE(switch_status_t
) switch_play_and_get_digits(switch_core_session_t
*session
,
2628 uint32_t min_digits
,
2629 uint32_t max_digits
,
2632 const char *valid_terminators
,
2633 const char *prompt_audio_file
,
2634 const char *bad_input_audio_file
,
2635 const char *var_name
,
2637 uint32_t digit_buffer_length
,
2638 const char *digits_regex
,
2639 uint32_t digit_timeout
,
2640 const char *transfer_on_failure
)
2642 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
2643 char *var_name_invalid
= NULL
;
2645 if (!zstr(digits_regex
) && !zstr(var_name
)) {
2646 var_name_invalid
= switch_mprintf("%s_invalid", var_name
);
2647 switch_channel_set_variable(channel
, var_name_invalid
, NULL
);
2648 switch_safe_free(var_name_invalid
);
2651 while (switch_channel_ready(channel
) && max_tries
) {
2652 switch_status_t status
;
2654 memset(digit_buffer
, 0, digit_buffer_length
);
2656 status
= switch_ivr_read(session
, min_digits
, max_digits
, prompt_audio_file
, var_name
,
2657 digit_buffer
, digit_buffer_length
, timeout
, valid_terminators
, digit_timeout
);
2659 if (status
== SWITCH_STATUS_RESTART
) {
2663 if (status
== SWITCH_STATUS_TIMEOUT
&& strlen(digit_buffer
) >= min_digits
) {
2664 status
= SWITCH_STATUS_SUCCESS
;
2667 if ((min_digits
== 0) && (strlen(digit_buffer
) == 0) && switch_channel_get_variable(channel
, SWITCH_READ_TERMINATOR_USED_VARIABLE
) != 0)
2669 return SWITCH_STATUS_SUCCESS
;
2672 if (!(status
== SWITCH_STATUS_TOO_SMALL
&& strlen(digit_buffer
) == 0)) {
2673 if (status
== SWITCH_STATUS_SUCCESS
) {
2674 if (!zstr(digit_buffer
)) {
2675 if (zstr(digits_regex
)) {
2676 return SWITCH_STATUS_SUCCESS
;
2678 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG1
, "Test Regex [%s][%s]\n", digit_buffer
, digits_regex
);
2680 if (switch_regex_match(digit_buffer
, digits_regex
) == SWITCH_STATUS_SUCCESS
) {
2681 return SWITCH_STATUS_SUCCESS
;
2683 switch_channel_set_variable(channel
, var_name
, NULL
);
2684 if (!zstr(var_name
)) {
2685 var_name_invalid
= switch_mprintf("%s_invalid", var_name
);
2686 switch_channel_set_variable(channel
, var_name_invalid
, digit_buffer
);
2687 switch_safe_free(var_name_invalid
);
2694 if (!switch_channel_ready(channel
)) {
2698 switch_ivr_play_file(session
, NULL
, bad_input_audio_file
, NULL
);
2702 memset(digit_buffer
, 0, digit_buffer_length
);
2704 /* If we get here then check for transfer-on-failure ext/dp/context */
2705 /* split this arg on spaces to get ext, dp, and context */
2707 if (!zstr(transfer_on_failure
)) {
2708 const char *failure_ext
= NULL
;
2709 const char *failure_dialplan
= NULL
;
2710 const char *failure_context
= NULL
;
2712 char *mydata
= switch_core_session_strdup(session
, transfer_on_failure
);
2715 argc
= switch_separate_string(mydata
, ' ', target
, (sizeof(target
) / sizeof(target
[0])));
2718 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
,"Bad target for PAGD failure: [%s]\n", transfer_on_failure
);
2719 return SWITCH_STATUS_FALSE
;
2723 failure_ext
= target
[0];
2727 failure_dialplan
= target
[1];
2731 failure_context
= target
[2];
2734 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
,
2735 "PAGD failure! Transfer to: %s / %s / %s\n", failure_ext
, failure_dialplan
, failure_context
);
2737 switch_ivr_session_transfer(session
,failure_ext
, failure_dialplan
, failure_context
);
2738 return SWITCH_STATUS_FALSE
;
2741 return SWITCH_STATUS_FALSE
;
2744 SWITCH_DECLARE(switch_status_t
) switch_ivr_speak_text_handle(switch_core_session_t
*session
,
2745 switch_speech_handle_t
*sh
,
2746 switch_codec_t
*codec
, switch_timer_t
*timer
, const char *text
, switch_input_args_t
*args
)
2748 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
2749 short abuf
[SWITCH_RECOMMENDED_BUFFER_SIZE
];
2750 switch_dtmf_t dtmf
= { 0 };
2752 switch_size_t ilen
= 0;
2753 switch_frame_t write_frame
= { 0 };
2754 switch_status_t status
= SWITCH_STATUS_SUCCESS
;
2755 switch_speech_flag_t flags
= SWITCH_SPEECH_FLAG_NONE
;
2756 switch_size_t extra
= 0;
2758 const char *star
, *pound
, *p
;
2759 switch_size_t starlen
, poundlen
;
2762 return SWITCH_STATUS_FALSE
;
2765 if (switch_channel_pre_answer(channel
) != SWITCH_STATUS_SUCCESS
) {
2766 return SWITCH_STATUS_FALSE
;
2769 if (!switch_core_codec_ready(codec
)) {
2770 return SWITCH_STATUS_FALSE
;
2773 arg_recursion_check_start(args
);
2775 write_frame
.data
= abuf
;
2776 write_frame
.buflen
= sizeof(abuf
);
2778 len
= sh
->samples
* 2 * sh
->channels
;
2782 if (!(star
= switch_channel_get_variable(channel
, "star_replace"))) {
2785 if (!(pound
= switch_channel_get_variable(channel
, "pound_replace"))) {
2788 starlen
= strlen(star
);
2789 poundlen
= strlen(pound
);
2792 for (p
= text
; p
&& *p
; p
++) {
2795 } else if (*p
== '#') {
2802 switch_size_t mylen
= strlen(text
) + extra
+ 1;
2803 tmp
= malloc(mylen
);
2805 arg_recursion_check_stop(args
);
2806 return SWITCH_STATUS_MEMERR
;
2808 memset(tmp
, 0, mylen
);
2810 for (p
= text
; p
&& *p
; p
++) {
2812 snprintf(tp
+ strlen(tp
), sizeof(tp
) - strlen(tp
), "%s", star
);
2814 } else if (*p
== '#') {
2815 snprintf(tp
+ strlen(tp
), sizeof(tp
) - strlen(tp
), "%s", pound
);
2825 switch_core_speech_feed_tts(sh
, text
, &flags
);
2826 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "Speaking text: %s\n", text
);
2827 switch_safe_free(tmp
);
2830 write_frame
.rate
= sh
->rate
;
2831 memset(write_frame
.data
, 0, len
);
2832 write_frame
.datalen
= len
;
2833 write_frame
.samples
= len
/ 2;
2834 write_frame
.codec
= codec
;
2836 switch_assert(codec
->implementation
!= NULL
);
2838 switch_channel_audio_sync(channel
);
2842 switch_event_t
*event
;
2846 if (!switch_channel_ready(channel
)) {
2847 status
= SWITCH_STATUS_FALSE
;
2851 if (switch_channel_test_flag(channel
, CF_BREAK
)) {
2852 switch_channel_clear_flag(channel
, CF_BREAK
);
2853 status
= SWITCH_STATUS_BREAK
;
2857 switch_ivr_parse_all_events(session
);
2860 /* dtmf handler function you can hook up to be executed when a digit is dialed during playback
2861 * if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
2863 if (switch_channel_has_dtmf(channel
)) {
2864 if (!args
->input_callback
&& !args
->buf
&& !args
->dmachine
) {
2865 status
= SWITCH_STATUS_BREAK
;
2868 if (args
->buf
&& !strcasecmp(args
->buf
, "_break_")) {
2869 status
= SWITCH_STATUS_BREAK
;
2871 switch_channel_dequeue_dtmf(channel
, &dtmf
);
2873 if (args
->dmachine
) {
2874 char ds
[2] = {dtmf
.digit
, '\0'};
2875 if ((status
= switch_ivr_dmachine_feed(args
->dmachine
, ds
, NULL
)) != SWITCH_STATUS_SUCCESS
) {
2880 if (args
->input_callback
) {
2881 status
= args
->input_callback(session
, (void *) &dtmf
, SWITCH_INPUT_TYPE_DTMF
, args
->buf
, args
->buflen
);
2882 } else if (args
->buf
) {
2883 *((char *) args
->buf
) = dtmf
.digit
;
2884 status
= SWITCH_STATUS_BREAK
;
2889 if (args
->input_callback
) {
2890 if (switch_core_session_dequeue_event(session
, &event
, SWITCH_FALSE
) == SWITCH_STATUS_SUCCESS
) {
2891 switch_status_t ostatus
= args
->input_callback(session
, event
, SWITCH_INPUT_TYPE_EVENT
, args
->buf
, args
->buflen
);
2892 if (ostatus
!= SWITCH_STATUS_SUCCESS
) {
2895 switch_event_destroy(&event
);
2899 if (status
!= SWITCH_STATUS_SUCCESS
) {
2904 if (switch_test_flag(sh
, SWITCH_SPEECH_FLAG_PAUSE
)) {
2906 if (switch_core_timer_next(timer
) != SWITCH_STATUS_SUCCESS
) {
2910 switch_frame_t
*read_frame
;
2911 switch_status_t tstatus
= switch_core_session_read_frame(session
, &read_frame
, SWITCH_IO_FLAG_NONE
, 0);
2913 while (switch_channel_ready(channel
) && switch_channel_test_flag(channel
, CF_HOLD
)) {
2914 switch_ivr_parse_all_messages(session
);
2915 switch_yield(10000);
2918 if (!SWITCH_READ_ACCEPTABLE(tstatus
)) {
2922 if (args
&& args
->dmachine
) {
2923 if ((status
= switch_ivr_dmachine_ping(args
->dmachine
, NULL
)) != SWITCH_STATUS_SUCCESS
) {
2928 if (args
&& (args
->read_frame_callback
)) {
2929 if ((status
= args
->read_frame_callback(session
, read_frame
, args
->user_data
)) != SWITCH_STATUS_SUCCESS
) {
2938 flags
= SWITCH_SPEECH_FLAG_BLOCKING
;
2939 status
= switch_core_speech_read_tts(sh
, abuf
, &ilen
, &flags
);
2941 if (status
!= SWITCH_STATUS_SUCCESS
) {
2942 if (status
== SWITCH_STATUS_BREAK
) {
2943 status
= SWITCH_STATUS_SUCCESS
;
2948 write_frame
.datalen
= (uint32_t) ilen
;
2949 write_frame
.samples
= (uint32_t) (ilen
/ 2 / sh
->channels
);
2951 write_frame
.timestamp
= timer
->samplecount
;
2953 if (switch_core_session_write_frame(session
, &write_frame
, SWITCH_IO_FLAG_NONE
, 0) != SWITCH_STATUS_SUCCESS
) {
2958 if (switch_core_timer_next(timer
) != SWITCH_STATUS_SUCCESS
) {
2961 } else { /* time off the channel (if you must) */
2962 switch_frame_t
*read_frame
;
2963 switch_status_t tstatus
= switch_core_session_read_frame(session
, &read_frame
, SWITCH_IO_FLAG_NONE
, 0);
2965 while (switch_channel_ready(channel
) && switch_channel_test_flag(channel
, CF_HOLD
)) {
2966 switch_ivr_parse_all_messages(session
);
2967 switch_yield(10000);
2970 if (!SWITCH_READ_ACCEPTABLE(tstatus
)) {
2974 if (args
&& args
->dmachine
) {
2975 if ((status
= switch_ivr_dmachine_ping(args
->dmachine
, NULL
)) != SWITCH_STATUS_SUCCESS
) {
2980 if (args
&& (args
->read_frame_callback
)) {
2981 if ((status
= args
->read_frame_callback(session
, read_frame
, args
->user_data
)) != SWITCH_STATUS_SUCCESS
) {
2990 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "done speaking text\n");
2992 switch_core_speech_flush_tts(sh
);
2994 arg_recursion_check_stop(args
);
2998 struct cached_speech_handle
{
3000 char voice_name
[80];
3001 switch_speech_handle_t sh
;
3002 switch_codec_t codec
;
3003 switch_timer_t timer
;
3006 typedef struct cached_speech_handle cached_speech_handle_t
;
3008 SWITCH_DECLARE(void) switch_ivr_clear_speech_cache(switch_core_session_t
*session
)
3010 cached_speech_handle_t
*cache_obj
= NULL
;
3011 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
3013 if ((cache_obj
= switch_channel_get_private(channel
, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME
))) {
3014 switch_speech_flag_t flags
= SWITCH_SPEECH_FLAG_NONE
;
3015 if (cache_obj
->timer
.interval
) {
3016 switch_core_timer_destroy(&cache_obj
->timer
);
3018 if (cache_obj
->sh
.speech_interface
) {
3019 switch_core_speech_close(&cache_obj
->sh
, &flags
);
3021 switch_core_codec_destroy(&cache_obj
->codec
);
3022 switch_channel_set_private(channel
, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME
, NULL
);
3026 SWITCH_DECLARE(switch_status_t
) switch_ivr_speak_text(switch_core_session_t
*session
,
3027 const char *tts_name
, const char *voice_name
, const char *text
, switch_input_args_t
*args
)
3029 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
3033 switch_frame_t write_frame
= { 0 };
3034 switch_timer_t ltimer
, *timer
;
3035 switch_codec_t lcodec
, *codec
;
3036 switch_memory_pool_t
*pool
= switch_core_session_get_pool(session
);
3038 switch_status_t status
= SWITCH_STATUS_SUCCESS
;
3039 switch_speech_handle_t lsh
, *sh
;
3040 switch_speech_flag_t flags
= SWITCH_SPEECH_FLAG_NONE
;
3041 const char *timer_name
, *var
;
3042 cached_speech_handle_t
*cache_obj
= NULL
;
3043 int need_create
= 1, need_alloc
= 1;
3044 switch_codec_implementation_t read_impl
= { 0 };
3045 switch_core_session_get_read_impl(session
, &read_impl
);
3047 if (switch_channel_pre_answer(channel
) != SWITCH_STATUS_SUCCESS
) {
3048 return SWITCH_STATUS_FALSE
;
3051 arg_recursion_check_start(args
);
3057 if ((var
= switch_channel_get_variable(channel
, SWITCH_CACHE_SPEECH_HANDLES_VARIABLE
)) && switch_true(var
)) {
3058 if ((cache_obj
= (cached_speech_handle_t
*) switch_channel_get_private(channel
, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME
))) {
3060 if (!strcasecmp(cache_obj
->tts_name
, tts_name
)) {
3063 switch_ivr_clear_speech_cache(session
);
3068 cache_obj
= (cached_speech_handle_t
*) switch_core_session_alloc(session
, sizeof(*cache_obj
));
3071 switch_copy_string(cache_obj
->tts_name
, tts_name
, sizeof(cache_obj
->tts_name
));
3072 switch_copy_string(cache_obj
->voice_name
, voice_name
, sizeof(cache_obj
->voice_name
));
3073 switch_channel_set_private(channel
, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME
, cache_obj
);
3075 sh
= &cache_obj
->sh
;
3076 codec
= &cache_obj
->codec
;
3077 timer
= &cache_obj
->timer
;
3080 timer_name
= switch_channel_get_variable(channel
, "timer_name");
3082 switch_core_session_reset(session
, SWITCH_FALSE
, SWITCH_FALSE
);
3084 rate
= read_impl
.actual_samples_per_second
;
3085 interval
= read_impl
.microseconds_per_packet
/ 1000;
3086 channels
= read_impl
.number_of_channels
;
3089 memset(sh
, 0, sizeof(*sh
));
3090 if ((status
= switch_core_speech_open(sh
, tts_name
, voice_name
, (uint32_t) rate
, interval
, read_impl
.number_of_channels
, &flags
, NULL
)) != SWITCH_STATUS_SUCCESS
) {
3091 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Invalid TTS module %s[%s]!\n", tts_name
, voice_name
);
3092 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_TRUE
);
3093 switch_ivr_clear_speech_cache(session
);
3094 arg_recursion_check_stop(args
);
3097 } else if (cache_obj
&& strcasecmp(cache_obj
->voice_name
, voice_name
)) {
3098 switch_copy_string(cache_obj
->voice_name
, voice_name
, sizeof(cache_obj
->voice_name
));
3099 switch_core_speech_text_param_tts(sh
, "voice", voice_name
);
3102 if (switch_channel_pre_answer(channel
) != SWITCH_STATUS_SUCCESS
) {
3104 switch_core_speech_close(sh
, &flags
);
3105 arg_recursion_check_stop(args
);
3106 return SWITCH_STATUS_FALSE
;
3108 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "OPEN TTS %s\n", tts_name
);
3113 if (switch_core_codec_init(codec
,
3116 NULL
, (int) rate
, interval
, channels
, SWITCH_CODEC_FLAG_ENCODE
| SWITCH_CODEC_FLAG_DECODE
, NULL
,
3117 pool
) == SWITCH_STATUS_SUCCESS
) {
3118 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "Raw Codec Activated\n");
3120 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "Raw Codec Activation Failed %s@%uhz 1 channel %dms\n", codec_name
,
3123 switch_core_speech_close(sh
, &flags
);
3124 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_TRUE
);
3125 switch_ivr_clear_speech_cache(session
);
3126 arg_recursion_check_stop(args
);
3127 return SWITCH_STATUS_GENERR
;
3131 write_frame
.codec
= codec
;
3135 if (switch_core_timer_init(timer
, timer_name
, interval
, (int) sh
->samples
, pool
) != SWITCH_STATUS_SUCCESS
) {
3136 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Setup timer failed!\n");
3137 switch_core_codec_destroy(write_frame
.codec
);
3139 switch_core_speech_close(sh
, &flags
);
3140 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_TRUE
);
3141 switch_ivr_clear_speech_cache(session
);
3142 arg_recursion_check_stop(args
);
3143 return SWITCH_STATUS_GENERR
;
3145 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "Setup timer success %u bytes per %d ms!\n", sh
->samples
* 2,
3148 switch_core_timer_sync(timer
); // Sync timer
3150 /* start a thread to absorb incoming audio */
3151 switch_core_service_session(session
);
3155 status
= switch_ivr_speak_text_handle(session
, sh
, write_frame
.codec
, timer_name
? timer
: NULL
, text
, args
);
3159 switch_core_speech_close(sh
, &flags
);
3160 switch_core_codec_destroy(codec
);
3164 /* End the audio absorbing thread */
3165 switch_core_thread_session_end(session
);
3167 switch_core_timer_destroy(timer
);
3171 switch_core_session_reset(session
, SWITCH_FALSE
, SWITCH_TRUE
);
3172 arg_recursion_check_stop(args
);
3178 static switch_status_t
hold_on_dtmf(switch_core_session_t
*session
, void *input
, switch_input_type_t itype
, void *buf
, unsigned int buflen
)
3180 char *stop_key
= (char *) buf
;
3183 case SWITCH_INPUT_TYPE_DTMF
:
3185 switch_dtmf_t
*dtmf
= (switch_dtmf_t
*) input
;
3186 if (dtmf
->digit
== *stop_key
) {
3187 return SWITCH_STATUS_BREAK
;
3195 return SWITCH_STATUS_SUCCESS
;
3198 SWITCH_DECLARE(switch_status_t
) switch_ivr_soft_hold(switch_core_session_t
*session
, const char *unhold_key
, const char *moh_a
, const char *moh_b
)
3200 switch_channel_t
*channel
, *other_channel
;
3201 switch_core_session_t
*other_session
;
3202 const char *other_uuid
, *moh
= NULL
;
3204 switch_input_args_t args
= { 0 };
3205 args
.input_callback
= hold_on_dtmf
;
3206 args
.buf
= (void *) unhold_key
;
3207 args
.buflen
= (uint32_t) strlen(unhold_key
);
3209 switch_assert(session
!= NULL
);
3210 channel
= switch_core_session_get_channel(session
);
3211 switch_assert(channel
!= NULL
);
3213 if ((other_uuid
= switch_channel_get_partner_uuid(channel
))) {
3214 if ((other_session
= switch_core_session_locate(other_uuid
))) {
3215 other_channel
= switch_core_session_get_channel(other_session
);
3220 moh
= switch_channel_get_hold_music(other_channel
);
3223 if (!zstr(moh
) && strcasecmp(moh
, "silence") && !switch_channel_test_flag(other_channel
, CF_BROADCAST
)) {
3224 switch_ivr_broadcast(other_uuid
, moh
, SMF_ECHO_ALEG
| SMF_LOOP
);
3231 moh
= switch_channel_get_hold_music(channel
);
3234 if (!zstr(moh
) && strcasecmp(moh
, "silence")) {
3235 switch_ivr_play_file(session
, NULL
, moh
, &args
);
3237 switch_ivr_collect_digits_callback(session
, &args
, 0, 0);
3241 switch_channel_stop_broadcast(other_channel
);
3244 switch_core_session_rwunlock(other_session
);
3247 return SWITCH_STATUS_SUCCESS
;
3252 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Channel %s is not in a bridge\n", switch_channel_get_name(channel
));
3253 return SWITCH_STATUS_FALSE
;
3260 /** playing initial prompt - allow barge in */
3261 SWITCH_COLLECT_INPUT_PROMPT
= (1 << 0),
3262 /** looking for speech input */
3263 SWITCH_COLLECT_INPUT_SPEECH
= (1 << 1),
3264 /** finished looking for speech input */
3265 SWITCH_COLLECT_INPUT_SPEECH_DONE
= (1 << 2),
3266 /** looking for digits */
3267 SWITCH_COLLECT_INPUT_DIGITS
= (1 << 3),
3268 /** finished looking for digits */
3269 SWITCH_COLLECT_INPUT_DIGITS_DONE
= (1 << 4)
3270 } switch_collect_input_flags_t
;
3274 cJSON
*recognition_result
;
3278 const char *terminators
;
3280 switch_time_t last_digit_time
;
3281 switch_bool_t is_speech
;
3282 switch_input_args_t
*original_args
;
3283 } switch_collect_input_state_t
;
3285 static void deliver_asr_event(switch_core_session_t
*session
, switch_event_t
*event
, switch_input_args_t
*args
)
3287 if (args
&& args
->input_callback
) {
3288 args
->input_callback(session
, (void *)event
, SWITCH_INPUT_TYPE_EVENT
, args
->buf
, args
->buflen
);
3292 static switch_status_t
switch_collect_input_callback(switch_core_session_t
*session
, void *input
, switch_input_type_t input_type
, void *data
, unsigned int len
)
3294 switch_collect_input_state_t
*state
= (switch_collect_input_state_t
*)data
;
3295 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
3297 if (switch_test_flag(state
, SWITCH_COLLECT_INPUT_SPEECH
) && input_type
== SWITCH_INPUT_TYPE_EVENT
) {
3298 const char *speech_type
= NULL
;
3299 switch_event_t
*event
= (switch_event_t
*)input
;
3301 if (event
->event_id
!= SWITCH_EVENT_DETECTED_SPEECH
) return SWITCH_STATUS_SUCCESS
;
3303 speech_type
= switch_event_get_header(event
, "Speech-Type");
3305 if (zstr(speech_type
)) return SWITCH_STATUS_SUCCESS
;
3307 deliver_asr_event(session
, event
, state
->original_args
);
3309 if (!strcasecmp(speech_type
, "detected-speech")) {
3310 const char *result
= switch_event_get_body(event
);
3312 /* stop waiting for speech */
3313 switch_set_flag(state
, SWITCH_COLLECT_INPUT_SPEECH_DONE
);
3315 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_INFO
, "(%s) DETECTED SPEECH %s\n", switch_channel_get_name(channel
), speech_type
);
3317 if (!zstr(result
)) {
3318 state
->recognition_result
= cJSON_Parse(result
);
3320 if (state
->recognition_result
) {
3321 const char *text
= cJSON_GetObjectCstr(state
->recognition_result
, "text");
3324 /* stop waiting for digits */
3325 switch_set_flag(state
, SWITCH_COLLECT_INPUT_DIGITS_DONE
);
3329 return SWITCH_STATUS_BREAK
;
3330 } else if (!strcasecmp(speech_type
, "detected-partial-speech")) {
3331 } else if (!strcasecmp("closed", speech_type
)) {
3332 /* stop waiting for speech */
3333 switch_set_flag(state
, SWITCH_COLLECT_INPUT_SPEECH_DONE
);
3334 return SWITCH_STATUS_BREAK
;
3335 } else if (!strcasecmp(speech_type
, "begin-speaking")) {
3336 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_INFO
, "(%s) START OF SPEECH\n", switch_channel_get_name(channel
));
3337 state
->is_speech
= SWITCH_TRUE
;
3339 if (switch_test_flag(state
, SWITCH_COLLECT_INPUT_PROMPT
)) {
3340 /* barge in on prompt */
3341 return SWITCH_STATUS_BREAK
;
3344 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_INFO
, "Unhandled Speech-Type %s\n", speech_type
);
3348 if (switch_test_flag(state
, SWITCH_COLLECT_INPUT_DIGITS
) && input_type
== SWITCH_INPUT_TYPE_DTMF
) {
3349 switch_dtmf_t
*dtmf
= (switch_dtmf_t
*) input
;
3350 state
->last_digit_time
= switch_micro_time_now();
3351 state
->is_speech
= SWITCH_FALSE
;
3353 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "\nis_speech = false; SWITCH_INPUT_TYPE_DTMF; last_digit_time=%" SWITCH_INT64_T_FMT
"\n", state
->last_digit_time
);
3355 if (!zstr(state
->terminators
) && strchr(state
->terminators
, dtmf
->digit
)) {
3356 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "(%s) ACCEPT TERMINATOR %c\n",
3357 switch_channel_get_name(channel
), dtmf
->digit
);
3359 state
->terminator
= dtmf
->digit
;
3361 /* stop waiting for digits */
3362 switch_set_flag(state
, SWITCH_COLLECT_INPUT_DIGITS_DONE
);
3364 if (switch_test_flag(state
, SWITCH_COLLECT_INPUT_DIGITS
) && !zstr(state
->digits
)) {
3365 /* stop waiting for speech */
3366 switch_set_flag(state
, SWITCH_COLLECT_INPUT_SPEECH_DONE
);
3369 /* barge-in and break playback on terminator */
3370 return SWITCH_STATUS_BREAK
;
3373 if (!switch_test_flag(state
, SWITCH_COLLECT_INPUT_DIGITS_DONE
)) {
3374 int digits_collected
= strlen(state
->digits
);
3376 if (digits_collected
< state
->max_digits
) {
3377 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "(%s) ACCEPT DIGIT %c\n",
3378 switch_channel_get_name(channel
), dtmf
->digit
);
3379 state
->digits
[digits_collected
] = dtmf
->digit
;
3382 if (digits_collected
+ 1 >= state
->max_digits
) {
3383 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "(%s) MAX DIGITS COLLECTED\n", switch_channel_get_name(channel
));
3384 switch_set_flag(state
, SWITCH_COLLECT_INPUT_DIGITS_DONE
); // stop waiting for digits
3385 switch_set_flag(state
, SWITCH_COLLECT_INPUT_SPEECH_DONE
); // stop waiting for speech, too
3388 return SWITCH_STATUS_BREAK
; // got a digit- break for inter-digit timeout / checking results / barge-in
3391 return SWITCH_STATUS_SUCCESS
;
3396 /*!\brief Play prompt and collect input
3398 * Returns collect status
3400 * \param[in] session the current session
3402 * \return Returns status
3403 * SWITCH_STATUS_SUCCESS when success
3404 * SWITCH_STATUS_FALSE when error
3405 * SWITCH_STATUS_GENERR when error
3407 SWITCH_DECLARE(switch_status_t
) switch_ivr_play_and_collect_input(switch_core_session_t
*session
,
3409 const char *recognizer_mod_name
,
3410 const char *recognizer_grammar
,
3413 const char *terminators
,
3414 uint32_t digit_timeout
,
3415 cJSON
**recognition_result
,
3416 char **digits_collected
,
3417 char *terminator_collected
,
3418 switch_input_args_t
*args
)
3420 switch_status_t status
= SWITCH_STATUS_FALSE
;
3421 switch_input_args_t myargs
= { 0 };
3422 switch_collect_input_state_t state
= { 0 };
3423 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
3425 arg_recursion_check_start(args
);
3427 /* configure digit collection */
3428 if (digit_timeout
<= 0) digit_timeout
= 5000;
3429 if (min_digits
< 0) {
3433 /* check if digit collection is enabled */
3434 if (min_digits
> 0) {
3435 if (max_digits
< min_digits
) {
3436 max_digits
= min_digits
;
3438 if (max_digits
> 100) {
3441 state
.digits
= switch_core_session_alloc(session
, sizeof(char) * (max_digits
+ 1));
3442 switch_set_flag(&state
, SWITCH_COLLECT_INPUT_DIGITS
);
3444 switch_set_flag(&state
, SWITCH_COLLECT_INPUT_DIGITS_DONE
);
3447 state
.min_digits
= min_digits
;
3448 state
.max_digits
= max_digits
;
3449 if (!zstr(terminators
)) {
3450 if (!strcasecmp(terminators
, "any")) {
3451 state
.terminators
= "1234567890*#";
3452 } else if (!strcasecmp(terminators
, "none")) {
3453 state
.terminators
= NULL
;
3455 state
.terminators
= terminators
;
3459 /* start speech recognition, if enabled */
3460 if (recognizer_grammar
&& recognizer_mod_name
) {
3461 if ((status
= switch_ivr_detect_speech(session
, recognizer_mod_name
, recognizer_grammar
, "", NULL
, NULL
)) != SWITCH_STATUS_SUCCESS
) {
3462 /* map SWITCH_STATUS_FALSE to SWITCH_STATUS_GENERR to indicate grammar load failed
3463 SWITCH_STATUS_NOT_INITALIZED will be passed back to indicate ASR resource problem */
3464 if (status
== SWITCH_STATUS_FALSE
) {
3465 status
= SWITCH_STATUS_GENERR
;
3469 switch_set_flag(&state
, SWITCH_COLLECT_INPUT_SPEECH
);
3471 switch_set_flag(&state
, SWITCH_COLLECT_INPUT_SPEECH_DONE
);
3474 /* play the prompt, looking for input result */
3477 state
.original_args
= args
;
3478 myargs
.dmachine
= args
->dmachine
;
3479 myargs
.read_frame_callback
= args
->read_frame_callback
;
3480 myargs
.user_data
= args
->user_data
;
3483 myargs
.input_callback
= switch_collect_input_callback
;
3484 myargs
.buf
= &state
;
3485 myargs
.buflen
= sizeof(state
);
3487 switch_set_flag(&state
, SWITCH_COLLECT_INPUT_PROMPT
);
3488 status
= switch_ivr_play_file(session
, NULL
, prompt
, &myargs
);
3489 switch_clear_flag(&state
, SWITCH_COLLECT_INPUT_PROMPT
);
3491 if (args
&& args
->dmachine
&& switch_ivr_dmachine_last_ping(args
->dmachine
) != SWITCH_STATUS_SUCCESS
) {
3492 switch_set_flag(&state
, SWITCH_COLLECT_INPUT_DIGITS_DONE
);
3493 switch_set_flag(&state
, SWITCH_COLLECT_INPUT_SPEECH_DONE
);
3494 status
= SWITCH_STATUS_SUCCESS
;
3497 if (status
!= SWITCH_STATUS_BREAK
&& status
!= SWITCH_STATUS_SUCCESS
) {
3498 status
= SWITCH_STATUS_FALSE
;
3502 // wait for final result if not done
3503 if (!switch_test_flag(&state
, SWITCH_COLLECT_INPUT_DIGITS_DONE
) || !switch_test_flag(&state
, SWITCH_COLLECT_INPUT_SPEECH_DONE
)) {
3504 int sleep_time
= digit_timeout
;
3506 if (switch_test_flag(&state
, SWITCH_COLLECT_INPUT_SPEECH
)) {
3507 switch_ivr_detect_speech_start_input_timers(session
);
3509 state
.last_digit_time
= switch_micro_time_now();
3511 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_INFO
, "(%s) WAITING FOR RESULT\n", switch_channel_get_name(channel
));
3513 while ((!switch_test_flag(&state
, SWITCH_COLLECT_INPUT_DIGITS_DONE
) || !switch_test_flag(&state
, SWITCH_COLLECT_INPUT_SPEECH_DONE
))
3514 && switch_channel_ready(channel
)) {
3516 status
= switch_ivr_sleep(session
, sleep_time
, SWITCH_FALSE
, &myargs
);
3518 if (args
&& args
->dmachine
&& switch_ivr_dmachine_last_ping(args
->dmachine
) != SWITCH_STATUS_SUCCESS
) {
3520 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "(%s) DMACHINE DONE\n", switch_channel_get_name(channel
));
3521 switch_set_flag(&state
, SWITCH_COLLECT_INPUT_DIGITS_DONE
);
3522 switch_set_flag(&state
, SWITCH_COLLECT_INPUT_SPEECH_DONE
);
3523 status
= SWITCH_STATUS_SUCCESS
;
3527 if (state
.terminator
!= 0) {
3528 switch_set_flag(&state
, SWITCH_COLLECT_INPUT_SPEECH_DONE
);
3529 status
= SWITCH_STATUS_SUCCESS
;
3530 sleep_time
= digit_timeout
;
3534 if (state
.is_speech
== SWITCH_FALSE
) {
3536 // calculating how much time has elapsed since the last digit was collected
3537 sleep_time
= (switch_micro_time_now() - state
.last_digit_time
) / 1000;
3539 if (sleep_time
>= digit_timeout
) {
3540 // too much time since last digit
3541 if (!switch_test_flag(&state
, SWITCH_COLLECT_INPUT_DIGITS_DONE
)) {
3542 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, " (%s) INTER-DIGIT TIMEOUT is_speech = false; sleep_time >= digit_timeout; sleep_time=%i; last_digit_time=%" SWITCH_INT64_T_FMT
"; digit_timeout=%lu \n", switch_channel_get_name(channel
), sleep_time
, state
.last_digit_time
, (unsigned long)digit_timeout
);
3543 switch_set_flag(&state
, SWITCH_COLLECT_INPUT_DIGITS_DONE
);
3545 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "\nis_speech = false; sleep_time >= digit_timeout; sleep_time=%i; last_digit_time=%" SWITCH_INT64_T_FMT
"; digit_timeout=%lu \n", sleep_time
, state
.last_digit_time
, (unsigned long)digit_timeout
);
3547 status
= SWITCH_STATUS_SUCCESS
;
3548 sleep_time
= digit_timeout
;
3550 // woke up early, sleep for remaining digit timeout
3551 sleep_time
= digit_timeout
- sleep_time
;
3554 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "\nis_speech = true; sleep_time < digit_timeout; sleep_time=%i; last_digit_time=%" SWITCH_INT64_T_FMT
"; digit_timeout=%lu \n", sleep_time
, state
.last_digit_time
, (unsigned long)digit_timeout
);
3557 if (status
!= SWITCH_STATUS_BREAK
&& status
!= SWITCH_STATUS_SUCCESS
) {
3558 // error of some sort
3559 status
= SWITCH_STATUS_FALSE
;
3568 if (status
== SWITCH_STATUS_BREAK
) {
3569 status
= SWITCH_STATUS_SUCCESS
;
3572 if (switch_test_flag(&state
, SWITCH_COLLECT_INPUT_SPEECH
)) {
3573 switch_ivr_pause_detect_speech(session
);
3576 if (!zstr(state
.digits
) && strlen(state
.digits
) >= state
.min_digits
) {
3577 /* got DTMF result */
3578 if (digits_collected
) {
3579 *digits_collected
= state
.digits
;
3582 if (state
.recognition_result
) {
3583 cJSON_Delete(state
.recognition_result
);
3585 } else if (state
.recognition_result
) {
3586 /* have some kind of recognition result or error */
3587 if (recognition_result
) {
3588 *recognition_result
= state
.recognition_result
;
3590 cJSON_Delete(state
.recognition_result
);
3594 if (terminator_collected
&& state
.terminator
!= 0) {
3595 *terminator_collected
= state
.terminator
;
3598 arg_recursion_check_stop(args
);
3608 * indent-tabs-mode:t
3613 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: