RTS API Documentation  1.10.11
switch_ivr_play_say.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2019, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
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/
11  *
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
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
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.
23  *
24  * Contributor(s):
25  *
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>
32  *
33  * switch_ivr_play_say.c -- IVR Library (functions to play or say audio)
34  *
35  */
36 
37 #include <switch.h>
38 
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)
41 {
42  switch_event_t *hint_data;
43  switch_xml_t cfg, xml = NULL, language = NULL, macros = NULL, phrases = NULL, macro, input, action;
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;
48  uint8_t done = 0, searched = 0;
49  int matches = 0;
50  const char *pause_val;
51  int pause = 100;
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;
56 
57 
58  if (!macro_name) {
59  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No phrase macro specified.\n");
60  return status;
61  }
62 
64 
65  if (!lang) {
66  chan_lang = switch_channel_get_variable(channel, "default_language");
67  if (!chan_lang) {
68  chan_lang = "en";
69  }
70  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang);
71  } else {
72  chan_lang = lang;
73  }
74 
76  switch_assert(hint_data);
77 
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);
80  if (data) {
81  switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "data", data);
82  if (event) {
84  }
85  } else {
86  data = "";
87  }
88  switch_channel_event_set_data(channel, hint_data);
89 
90  if (switch_xml_locate_language(&xml, &cfg, hint_data, &language, &phrases, &macros, chan_lang) != SWITCH_STATUS_SUCCESS) {
91  goto done;
92  }
93 
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");
97  } else {
98  module_name = chan_lang;
99  }
100 
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");
104  }
105  }
106 
107  if (!(tts_engine = (char *) switch_xml_attr(language, "tts-engine"))) {
108  tts_engine = (char *) switch_xml_attr(language, "tts_engine");
109  }
110 
111  if (!(tts_voice = (char *) switch_xml_attr(language, "tts-voice"))) {
112  tts_voice = (char *) switch_xml_attr(language, "tts_voice");
113  }
114 
115  /* If we use the new structure, check for a group name */
116  if (language != macros) {
117  char *p;
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;
121 
122  if ((p = strchr(macro_name_dup, '@'))) {
123  *p++ = '\0';
124  local_macro_name = macro_name_dup;
125  group_macro_name = p;
126 
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);
129  goto done;
130  }
131  }
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;
135  }
136 
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);
140  }
141 
142  }
143 
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);
146  goto done;
147  }
148 
149  if (sound_path && sound_prefix_enforced == SWITCH_FALSE) {
150  char *p;
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);
155  }
156 
157  if ((pause_val = switch_xml_attr(macro, "pause"))) {
158  int tmp = atoi(pause_val);
159  if (tmp >= 0) {
160  pause = tmp;
161  }
162  }
163 
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");
166  goto done;
167  }
168 
170  status = SWITCH_STATUS_FALSE;
171  goto done;
172  }
173 
174  while (input) {
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;
183 
184  searched = 1;
185  if (!field) {
186  field = (char *) data;
187  }
188  if (event) {
189  field_expanded_alloc = switch_event_expand_headers(event, field);
190  } else {
191  field_expanded_alloc = switch_channel_expand_variables(channel, field);
192  }
193 
194  if (field_expanded_alloc == field) {
195  field_expanded_alloc = NULL;
196  field_expanded = field;
197  } else {
198  field_expanded = field_expanded_alloc;
199  }
200 
201  if (!pattern) {
202  pattern = ".*";
203  }
204 
205  status = SWITCH_STATUS_SUCCESS;
206 
207  if ((proceed = switch_regex_perform(field_expanded, pattern, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
208  match = switch_xml_child(input, "match");
209  } else {
210  match = switch_xml_child(input, "nomatch");
211  }
212 
213  if (match) {
214  matches++;
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;
219  uint32_t len = 0;
220  char *odata = NULL;
221  char *expanded = NULL;
222 
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");
228  switch_safe_free(field_expanded_alloc);
229  goto done;
230  }
231  memset(substituted, 0, len);
232  switch_perform_substitution(re, proceed, adata, field_expanded, substituted, len, ovector);
233  odata = substituted;
234  } else {
235  odata = adata;
236  }
237 
238  if (event) {
239  expanded = switch_event_expand_headers(event, odata);
240  } else {
241  expanded = switch_channel_expand_variables(channel, odata);
242  }
243 
244  if (expanded == odata) {
245  expanded = NULL;
246  } else {
247  odata = expanded;
248  }
249 
250  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Handle %s:[%s] (%s:%s)\n", func, odata, chan_lang,
251  module_name);
252 
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);
258 
260  pfh.volgranular = volume;
261 
262  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setting playback volume to %d\n", pfh.volgranular);
263  }
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")) {
272  char *cmd, *cmd_args;
273  status = SWITCH_STATUS_FALSE;
274 
275  cmd = switch_core_session_strdup(session, odata);
276  cmd_args = switch_separate_paren_args(cmd);
277 
278  if (!cmd_args) {
279  cmd_args = "";
280  }
281 
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);
285  } else {
286  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Application %s\n", cmd);
287  }
288  } else if (!strcasecmp(func, "say")) {
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};
295 
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);
299 
300  status = si->say_function(session, odata, &say_args, args);
301  } else {
302  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid SAY Interface [%s]!\n", module_name);
303  }
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");
307 
308  if (!my_tts_engine) {
309  my_tts_engine = tts_engine;
310  }
311 
312  if (!my_tts_voice) {
313  my_tts_voice = tts_voice;
314  }
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");
317  } else {
318  status = switch_ivr_speak_text(session, my_tts_engine, my_tts_voice, odata, args);
319  }
320  }
321 
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;
326  }
327  }
328 
330  switch_safe_free(field_expanded_alloc);
331 
332  if (done || status != SWITCH_STATUS_SUCCESS
333  || (match && do_break && switch_true(do_break))) {
334  break;
335  }
336 
337  input = input->next;
338  }
339 
340  done:
341 
343 
344  if (hint_data) {
345  switch_event_destroy(&hint_data);
346  }
347 
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);
350  }
351 
352  if (old_sound_prefix) {
353  switch_channel_set_variable(channel, "sound_prefix", old_sound_prefix);
354  }
355  if (local_sound_prefix_enforced == SWITCH_TRUE) {
356  switch_channel_set_variable(channel, "sound_prefix_enforced", NULL);
357  }
358 
359  if (xml) {
360  switch_xml_free(xml);
361  }
362 
363  return status;
364 }
365 
367 {
369  if (vars) {
370  for (hi = vars->headers; hi; hi = hi->next) {
371  char buf[1024];
372  char *vvar = NULL, *vval = NULL;
373 
374  vvar = (char *) hi->name;
375  vval = (char *) hi->value;
376 
377  switch_assert(vvar && vval);
378  switch_snprintf(buf, sizeof(buf), "Recording-Variable-%s", vvar);
380  }
381  }
382 }
383 
384 static const char *get_recording_var(switch_channel_t *channel, switch_event_t *vars, switch_file_handle_t *fh, const char *name)
385 {
386  const char *val = NULL;
387  if (vars) {
388  val = switch_event_get_header(vars, name);
389  }
390  if (!val && fh && fh->params) {
391  val = switch_event_get_header(fh->params, name);
392  }
393  if (!val) {
394  val = switch_channel_get_variable(channel, name);
395  }
396  return val;
397 }
398 
399 static int recording_var_true(switch_channel_t *channel, switch_event_t *vars, switch_file_handle_t *fh, const char *name)
400 {
401  return switch_true(get_recording_var(channel, vars, fh, name));
402 }
403 
405  switch_file_handle_t *fh, const char *file, switch_input_args_t *args, uint32_t limit, switch_event_t *vars)
406 {
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 };
414  char *codec_name;
416  const char *p;
417  const char *vval;
418  time_t start = 0;
419  uint32_t org_silence_hits = 0;
420  int asis = 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;
427  int divisor = 0;
429  int restart_limit_on_dtmf = 0;
430  const char *prefix, *var, *video_file = NULL;
432  int echo_on = 0;
433  const char *file_trimmed_ms = NULL;
434  const char *file_size = NULL;
435  const char *file_trimmed = NULL;
436 
438  return SWITCH_STATUS_FALSE;
439  }
440 
441  if (!file) {
442  return SWITCH_STATUS_FALSE;
443  }
444 
445  prefix = get_recording_var(channel, vars, fh, "sound_prefix");
446 
447  if (!prefix) {
449  }
450 
451  if (!switch_channel_media_ready(channel)) {
452  return SWITCH_STATUS_FALSE;
453  }
454 
455  switch_core_session_get_read_impl(session, &read_impl);
456 
457  if (!(divisor = read_impl.actual_samples_per_second / 8000)) {
458  divisor = 1;
459  }
460 
462 
463  if (!fh) {
464  fh = &lfh;
465  }
466 
467  fh->channels = read_impl.number_of_channels;
468  fh->native_rate = read_impl.actual_samples_per_second;
469 
470  if (fh->samples > 0) {
471  sample_start = fh->samples;
472  fh->samples = 0;
473  }
474 
475 
476  if ((p = get_recording_var(channel, vars, fh, "record_sample_rate"))) {
477  int tmp = 0;
478 
479  tmp = atoi(p);
480 
481  if (switch_is_valid_rate(tmp)) {
482  fh->samplerate = tmp;
483  }
484  }
485 
486  if (!strstr(file, SWITCH_URL_SEPARATOR)) {
487  char *ext;
488 
489  if (!switch_is_file_path(file)) {
490  char *tfile = NULL;
491  char *e;
492 
493  if (*file == '{') {
494  tfile = switch_core_session_strdup(session, file);
495 
496  while (*file == '{') {
497  if ((e = switch_find_end_paren(tfile, '{', '}'))) {
498  *e = '\0';
499  file = e + 1;
500  while(*file == ' ') file++;
501  } else {
502  tfile = NULL;
503  break;
504  }
505  }
506  }
507 
508  file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "}" : "", prefix, SWITCH_PATH_SEPARATOR, file);
509  }
510  if ((ext = strrchr(file, '.'))) {
511  ext++;
512  } else {
513  ext = read_impl.iananame;
514  file = switch_core_session_sprintf(session, "%s.%s", file, ext);
515  asis = 1;
516  }
517  }
518 
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));
523  return SWITCH_STATUS_GENERR;
524  }
525 
526 
527  vval = get_recording_var(channel, vars, fh, "enable_file_write_buffering");
528  if (!vval || switch_true(vval)) {
530  }
531 
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;
534  }
535 
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;
538  }
539 
540  if (!fh->prefix) {
541  fh->prefix = prefix;
542  }
543 
544  if (switch_channel_test_flag(channel, CF_VIDEO)) {
545  switch_vid_params_t vid_params = { 0 };
546 
547  file_flags |= SWITCH_FILE_FLAG_VIDEO;
551  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to establish inbound video stream\n");
554  file_flags &= ~SWITCH_FILE_FLAG_VIDEO;
555  } else {
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;
560  }
561  }
562 
563  if (switch_core_file_open(fh, file, fh->channels, read_impl.actual_samples_per_second, file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
567  return SWITCH_STATUS_GENERR;
568  }
569 
570 
571  if ((p = get_recording_var(channel, vars, fh, "record_fill_cng"))) {
572  if (!strcasecmp(p, "true")) {
573  fill_cng = 1400;
574  } else {
575  if ((fill_cng = atoi(p)) < 0) {
576  fill_cng = 0;
577  }
578  }
579  }
580 
581  if ((p = switch_channel_get_variable(channel, "record_indication")) || (fh->params && (p = switch_event_get_header(fh->params, "record_indication")))) {
583  waste_resources = 1400;
584 
585  if (switch_core_file_open(&ind_fh,
586  p,
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");
590  }
591  }
592 
593  if ((p = get_recording_var(channel, vars, fh, "record_waste_resources"))) {
594 
595  if (!strcasecmp(p, "true")) {
596  waste_resources = 1400;
597  } else {
598  if ((waste_resources = atoi(p)) < 0) {
599  waste_resources = 0;
600  }
601  }
602  }
603 
604  if (fill_cng || waste_resources) {
605  if (switch_core_codec_init(&write_codec,
606  "L16",
607  NULL,
608  NULL,
609  read_impl.actual_samples_per_second,
610  read_impl.microseconds_per_packet / 1000,
611  read_impl.number_of_channels,
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;
620  } else {
622  return SWITCH_STATUS_FALSE;
623  }
624  }
625 
626 
627 
630 
631  if ((p = get_recording_var(channel, vars, fh, "record_play_video"))) {
632 
633  video_file = switch_core_session_strdup(session, p);
634 
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");
639  }
640 
644  } else {
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));
648  }
649  }
650 
651  if (!switch_test_flag(&vfh, SWITCH_FILE_OPEN)) {
652  echo_on = 1;
655  }
656 
658  } else if (switch_channel_test_flag(channel, CF_VIDEO)) {
660  }
661 
662  if (sample_start > 0) {
663  uint32_t pos = 0;
664  switch_core_file_seek(fh, &pos, sample_start, SEEK_SET);
666  fh->samples = 0;
667  }
668 
669 
671  asis = 1;
672  }
673 
674  restart_limit_on_dtmf = recording_var_true(channel, vars, fh, "record_restart_limit_on_dtmf");
675 
676  if ((p = get_recording_var(channel, vars, fh, "record_title"))) {
677  vval = switch_core_session_strdup(session, p);
679  switch_channel_set_variable(channel, "record_title", NULL);
680  }
681 
682  if ((p = get_recording_var(channel, vars, fh, "record_copyright"))) {
683  vval = switch_core_session_strdup(session, p);
685  switch_channel_set_variable(channel, "record_copyright", NULL);
686  }
687 
688  if ((p = get_recording_var(channel, vars, fh, "record_software"))) {
689  vval = switch_core_session_strdup(session, p);
691  switch_channel_set_variable(channel, "record_software", NULL);
692  }
693 
694  if ((p = get_recording_var(channel, vars, fh, "record_artist"))) {
695  vval = switch_core_session_strdup(session, p);
697  switch_channel_set_variable(channel, "record_artist", NULL);
698  }
699 
700  if ((p = get_recording_var(channel, vars, fh, "record_comment"))) {
701  vval = switch_core_session_strdup(session, p);
703  switch_channel_set_variable(channel, "record_comment", NULL);
704  }
705 
706  if ((p = get_recording_var(channel, vars, fh, "record_date"))) {
707  vval = switch_core_session_strdup(session, p);
709  switch_channel_set_variable(channel, "record_date", NULL);
710  }
711 
712 
713  switch_channel_set_variable(channel, "silence_hits_exhausted", "false");
714 
715  if (!asis) {
716  codec_name = "L16";
717  if (switch_core_codec_init(&codec,
718  codec_name,
719  NULL,
720  NULL,
721  read_impl.actual_samples_per_second,
722  read_impl.microseconds_per_packet / 1000,
723  read_impl.number_of_channels,
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);
728  } else {
730  "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, fh->samplerate,
731  fh->channels, read_impl.microseconds_per_packet / 1000);
733  if (echo_on) {
736  }
739  }
742 
745  return SWITCH_STATUS_GENERR;
746  }
747  }
748 
749  if (limit) {
750  start = switch_epoch_time_now(NULL);
751  }
752 
753  if (fh->thresh) {
754  if (asis) {
755  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Can't detect silence on a native recording.\n");
756  } else {
757  if (fh->silence_hits) {
758  fh->silence_hits = fh->samplerate * fh->silence_hits / read_impl.samples_per_packet;
759  } else {
760  fh->silence_hits = fh->samplerate * 3 / read_impl.samples_per_packet;
761  }
762  org_silence_hits = fh->silence_hits;
763  }
764  }
765 
766 
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);
772  }
773 
774  {
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);
778  }
779  switch_channel_execute_on(channel, "execute_on_record_start");
780  switch_channel_api_on(channel, "api_on_record_start");
781  }
782 
783  for (;;) {
784  switch_size_t len;
785 
786  if (!switch_channel_ready(channel)) {
787  status = SWITCH_STATUS_FALSE;
788  break;
789  }
790 
791  if (switch_channel_test_flag(channel, CF_BREAK)) {
793  status = SWITCH_STATUS_BREAK;
794  break;
795  }
796 
798 
799  if (start && (switch_epoch_time_now(NULL) - start) > limit) {
800  break;
801  }
802 
803  if (args) {
804  /*
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.
807  */
808  if (switch_channel_has_dtmf(channel)) {
809 
810  if (limit && restart_limit_on_dtmf) {
811  start = switch_epoch_time_now(NULL);
812  }
813 
814  if (!args->input_callback && !args->buf && !args->dmachine) {
815  status = SWITCH_STATUS_BREAK;
816  break;
817  }
818  switch_channel_dequeue_dtmf(channel, &dtmf);
819 
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) {
823  break;
824  }
825  }
826 
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;
832  }
833  }
834 
835  if (args->input_callback) {
836  switch_event_t *event = NULL;
837  switch_status_t ostatus;
838 
840  if ((ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) {
841  status = ostatus;
842  }
843 
844  switch_event_destroy(&event);
845  }
846  }
847 
848  if (status != SWITCH_STATUS_SUCCESS) {
849  break;
850  }
851  }
852 
853  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
854  if (!SWITCH_READ_ACCEPTABLE(status)) {
855  break;
856  }
857 
858  if (args && args->dmachine) {
859  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
860  break;
861  }
862  }
863 
864  if (args && (args->read_frame_callback)) {
865  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
866  break;
867  }
868  }
869 
870  if (switch_test_flag(&vfh, SWITCH_FILE_OPEN)) {
872 
874 
875  //switch_core_media_set_video_file(session, NULL, SWITCH_RW_WRITE);
876 
878 
880  memset(&vfh, 0, sizeof(vfh));
881 
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");
886  }
887 
889  //switch_core_media_set_video_file(session, &vfh, SWITCH_RW_WRITE);
891  } else {
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));
896  }
897 
899  }
900 
901  }
902 
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;
907  double energy = 0;
908 
909 
910  for (count = 0; count < samples * read_impl.number_of_channels; count++) {
911  energy += abs(fdata[j++]);
912  }
913 
914  score = (uint32_t) (energy / (samples / divisor));
915 
916  if (score < fh->thresh) {
917  if (!--fh->silence_hits) {
918  switch_channel_set_variable(channel, "silence_hits_exhausted", "true");
919  break;
920  }
921  } else {
922  fh->silence_hits = org_silence_hits;
923  }
924  }
925 
926  write_frame.datalen = read_impl.decoded_bytes_per_packet;
927  write_frame.samples = write_frame.datalen / 2;
928 
929  if (switch_test_flag(&ind_fh, SWITCH_FILE_OPEN)) {
931 
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;;
935  } else {
936  switch_core_file_close(&ind_fh);
937  }
938 
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);
943  }
944 
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;
948 
949  if (switch_core_file_write(fh, data, &len) != SWITCH_STATUS_SUCCESS) {
950  break;
951  }
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) {
955  break;
956  }
957  }
958 
959 
960  if (waste_resources || switch_test_flag(&ind_fh, SWITCH_FILE_OPEN)) {
962  break;
963  }
964  }
965  }
966 
967  if (fill_cng || waste_resources) {
968  switch_core_codec_destroy(&write_codec);
969  }
970 
972  if (echo_on) {
975  }
978  }
980 
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);
988  }
989  if (file_size) {
990  switch_channel_set_variable(channel, "record_record_file_size", file_size);
991  switch_channel_set_variable(channel, "record_file_size", file_size);
992  }
993  if (file_trimmed) {
994  switch_channel_set_variable(channel, "record_record_trimmed", file_trimmed);
995  switch_channel_set_variable(channel, "record_trimmed", file_trimmed);
996  }
998 
999 
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 };
1004 
1005  SWITCH_STANDARD_STREAM(stream);
1006 
1007  if ((data = strchr(cmd, ':'))) {
1008  *data++ = '\0';
1009  expanded = switch_channel_expand_variables(channel, data);
1010  }
1011 
1012  switch_api_execute(cmd, expanded, session, &stream);
1013 
1014  if (expanded && expanded != data) {
1015  free(expanded);
1016  }
1017 
1018  switch_safe_free(stream.data);
1019 
1020  }
1021 
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));
1025 
1026  }
1027 
1028  switch_channel_set_variable_printf(channel, "record_samples", "%d", fh->samples_out);
1029 
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);
1035  }
1036 
1037  {
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);
1041  }
1042  switch_channel_execute_on(channel, "execute_on_record_stop");
1043  switch_channel_api_on(channel, "api_on_record_stop");
1044  }
1045 
1047 
1049  return status;
1050 }
1051 
1053  switch_file_handle_t *fh, const char *file, switch_input_args_t *args, uint32_t limit)
1054 {
1055  return switch_ivr_record_file_event(session, fh, file, args, limit, NULL);
1056 }
1057 
1059 {
1060  switch_buffer_t *audio_buffer = ts->user_data;
1061  int wrote;
1062 
1063  if (!audio_buffer) {
1064  return -1;
1065  }
1066 
1067  wrote = teletone_mux_tones(ts, map);
1068  switch_buffer_write(audio_buffer, ts->buffer, wrote * 2);
1069 
1070  return 0;
1071 }
1072 
1074 {
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 };
1083  switch_codec_implementation_t read_impl = { 0 };
1084  switch_core_session_get_read_impl(session, &read_impl);
1085 
1087  return SWITCH_STATUS_FALSE;
1088  }
1089 
1090  if (switch_core_codec_init(&write_codec,
1091  "L16",
1092  NULL,
1093  NULL,
1094  read_impl.actual_samples_per_second,
1095  read_impl.microseconds_per_packet / 1000,
1098 
1099  return SWITCH_STATUS_FALSE;
1100  }
1101 
1103 
1104  memset(&ts, 0, sizeof(ts));
1105  write_frame.codec = &write_codec;
1106  write_frame.data = data;
1107  write_frame.buflen = sizeof(data);
1108 
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);
1114 
1115  if (loops) {
1116  switch_buffer_set_loops(audio_buffer, loops);
1117  }
1118 
1119  for (;;) {
1120  switch_status_t status;
1121 
1122  if (!switch_channel_ready(channel)) {
1123  break;
1124  }
1125 
1126  if (switch_channel_test_flag(channel, CF_BREAK)) {
1128  break;
1129  }
1130 
1131  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1132 
1133  if (!SWITCH_READ_ACCEPTABLE(status)) {
1134  break;
1135  }
1136 
1137  if (args && args->dmachine) {
1138  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
1139  break;
1140  }
1141  }
1142 
1143  if (args && (args->read_frame_callback)) {
1144  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
1145  break;
1146  }
1147  }
1148 
1149  switch_ivr_parse_all_events(session);
1150 
1151  if (args) {
1152  /*
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.
1155  */
1156  if (switch_channel_has_dtmf(channel)) {
1157  if (!args->input_callback && !args->buf && !args->dmachine) {
1158  break;
1159  }
1160  switch_channel_dequeue_dtmf(channel, &dtmf);
1161 
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) {
1165  break;
1166  }
1167  }
1168 
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;
1174  }
1175  }
1176 
1177  if (args->input_callback) {
1178  switch_event_t *event;
1179 
1181  switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
1182  if (ostatus != SWITCH_STATUS_SUCCESS) {
1183  status = ostatus;
1184  }
1185  switch_event_destroy(&event);
1186  }
1187  }
1188 
1189  if (status != SWITCH_STATUS_SUCCESS) {
1190  break;
1191  }
1192  }
1193 
1194  if ((write_frame.datalen = (uint32_t) switch_buffer_read_loop(audio_buffer, write_frame.data, read_impl.decoded_bytes_per_packet)) <= 0) {
1195  break;
1196  }
1197 
1198  write_frame.samples = write_frame.datalen / 2;
1199 
1201  break;
1202  }
1203  }
1204 
1205  switch_core_codec_destroy(&write_codec);
1206  switch_buffer_destroy(&audio_buffer);
1208 
1210 
1211  return SWITCH_STATUS_SUCCESS;
1212 }
1213 
1215 {
1216  switch_file_handle_t *fhp;
1218 
1219  *fh = NULL;
1221 
1222  if ((fhp = switch_channel_get_private(channel, "__fh"))) {
1223  *fh = fhp;
1224  return SWITCH_STATUS_SUCCESS;
1225  }
1226 
1228 
1229  return SWITCH_STATUS_FALSE;
1230 }
1231 
1233 {
1234  *fh = NULL;
1236 
1237  return SWITCH_STATUS_SUCCESS;
1238 }
1239 
1240 #define FILE_STARTSAMPLES 1024 * 32
1241 #define FILE_BLOCKSIZE 1024 * 8
1242 #define FILE_BUFSIZE 1024 * 64
1243 
1245 {
1247  int16_t *abuf = NULL;
1248  switch_dtmf_t dtmf = { 0 };
1249  uint32_t interval = 0, samples = 0, framelen, sample_start = 0, channels = 1;
1250  uint32_t ilen = 0;
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 };
1256  char *codec_name;
1259  const char *p;
1260  //char *title = "", *copyright = "", *software = "", *artist = "", *comment = "", *date = "";
1261  char *ext;
1262  char *backup_file = NULL;
1263  const char *backup_ext;
1264  const char *prefix;
1265  const char *timer_name;
1266  const char *prebuf;
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;
1272  int eof = 0;
1273  switch_size_t bread = 0;
1274  switch_codec_implementation_t read_impl = { 0 };
1275  char *file_dup;
1276  char *argv[128] = { 0 };
1277  int argc;
1278  int cur;
1279  int done = 0;
1280  int timeout_samples = 0;
1281  switch_bool_t timeout_as_success = SWITCH_FALSE;
1282  const char *var;
1283  int more_data = 0;
1284  switch_event_t *event;
1285  uint32_t test_native = 0, last_native = 0;
1286  uint32_t buflen = 0;
1287  int flags;
1288  int cumulative = 0;
1289  int last_speed = -1;
1290 
1292  return SWITCH_STATUS_FALSE;
1293  }
1294 
1295  switch_core_session_get_read_impl(session, &read_impl);
1296 
1297  if ((var = switch_channel_get_variable(channel, "playback_timeout_sec_cumulative"))) {
1298  int tmp = atoi(var);
1299  if (tmp > 1) {
1300  timeout_samples = read_impl.actual_samples_per_second * tmp;
1301  cumulative = 1;
1302  }
1303 
1304  } else if ((var = switch_channel_get_variable(channel, "playback_timeout_sec"))) {
1305  int tmp = atoi(var);
1306  if (tmp > 1) {
1307  timeout_samples = read_impl.actual_samples_per_second * tmp;
1308  }
1309  }
1310 
1311  if ((var = switch_channel_get_variable(channel, "playback_timeout_as_success"))) {
1312  if (switch_true(var)) {
1313  timeout_as_success = SWITCH_TRUE;
1314  }
1315  }
1316  if ((play_delimiter_val = switch_channel_get_variable(channel, "playback_delimiter"))) {
1317  play_delimiter = *play_delimiter_val;
1318 
1319  if ((sleep_val = switch_channel_get_variable(channel, "playback_sleep_val"))) {
1320  int tmp = atoi(sleep_val);
1321  if (tmp >= 0) {
1322  sleep_val_i = tmp;
1323  }
1324  }
1325  }
1326 
1327  prefix = switch_channel_get_variable(channel, "sound_prefix");
1328  timer_name = switch_channel_get_variable(channel, "timer_name");
1329 
1330  if (zstr(file) || !switch_channel_media_ready(channel)) {
1331  return SWITCH_STATUS_FALSE;
1332  }
1333 
1335 
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])));
1339  } else {
1340  argc = 1;
1341  argv[0] = (char *) file;
1342  }
1343 
1344  if (!fh) {
1345  fh = &lfh;
1346  memset(fh, 0, sizeof(lfh));
1347  }
1348 
1349  if (fh->samples > 0) {
1350  sample_start = fh->samples;
1351  fh->samples = 0;
1352  }
1353 
1354 
1355 
1356 
1357  for (cur = 0; switch_channel_ready(channel) && !done && cur < argc; cur++) {
1358  file = argv[cur];
1359  eof = 0;
1360 
1361  if (cur) {
1362  fh->samples = sample_start = 0;
1363  if (sleep_val_i) {
1364  status = switch_ivr_sleep(session, sleep_val_i, SWITCH_FALSE, args);
1365  if(status != SWITCH_STATUS_SUCCESS) {
1366  break;
1367  }
1368  }
1369  }
1370 
1371  status = SWITCH_STATUS_SUCCESS;
1372 
1373  if (strchr(file, ':')) {
1374  char *dup;
1375 
1376  if (!strncasecmp(file, "phrase:", 7)) {
1377  char *arg = NULL;
1378  const char *lang = switch_channel_get_variable(channel, "language");
1379  alt = file + 7;
1380  dup = switch_core_session_strdup(session, alt);
1381 
1382  if (dup) {
1383  if ((arg = strchr(dup, ':'))) {
1384  *arg++ = '\0';
1385  }
1386  if ((status = switch_ivr_phrase_macro(session, dup, arg, lang, args)) != SWITCH_STATUS_SUCCESS) {
1387  break;
1388  }
1389  continue;
1390  } else {
1391  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Args\n");
1392  continue;
1393  }
1394  } else if (!strncasecmp(file, "say:", 4)) {
1395  const char *engine = NULL, *voice = NULL, *text = NULL;
1396 
1397  alt = file + 4;
1398  text = alt;
1399  engine = switch_channel_get_variable(channel, "tts_engine");
1400  voice = switch_channel_get_variable(channel, "tts_voice");
1401 
1402  if (engine && text) {
1403  if ((status = switch_ivr_speak_text(session, engine, voice, (char *)text, args)) != SWITCH_STATUS_SUCCESS) {
1404  break;
1405  }
1406  } else {
1407  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Args\n");
1408  }
1409 
1410  continue;
1411  }
1412 
1413  }
1414 
1415  if (!prefix) {
1416  prefix = SWITCH_GLOBAL_dirs.base_dir;
1417  }
1418 
1419  if (!strstr(file, SWITCH_URL_SEPARATOR)) {
1420  if (!switch_is_file_path(file)) {
1421  char *tfile = NULL;
1422  char *e;
1423 
1424  if (*file == '{') {
1425  tfile = switch_core_session_strdup(session, file);
1426 
1427  while (*file == '{') {
1428  if ((e = switch_find_end_paren(tfile, '{', '}'))) {
1429  *e = '\0';
1430  file = e + 1;
1431  while(*file == ' ') file++;
1432  } else {
1433  tfile = NULL;
1434  break;
1435  }
1436  }
1437  }
1438 
1439  file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "}" : "", prefix, SWITCH_PATH_SEPARATOR, file);
1440  }
1441  if ((ext = strrchr(file, '.'))) {
1442  ext++;
1443  } else {
1444 
1445  if (!(backup_ext = switch_channel_get_variable(channel, "native_backup_extension"))) {
1446  backup_ext = "wav";
1447  }
1448 
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);
1452  }
1453  }
1454 
1455  if ((prebuf = switch_channel_get_variable(channel, "stream_prebuffer"))) {
1456  int maybe = atoi(prebuf);
1457  if (maybe > 0) {
1458  fh->prebuf = maybe;
1459  }
1460  }
1461 
1462 
1463  if (!fh->prefix) {
1464  fh->prefix = prefix;
1465  }
1466 
1468 
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);
1472  }
1473 
1474 
1475  for(;;) {
1476  if (switch_core_file_open(fh,
1477  file,
1478  read_impl.number_of_channels,
1479  read_impl.actual_samples_per_second, flags, NULL) == SWITCH_STATUS_SUCCESS) {
1480  break;
1481  }
1482 
1483  if (backup_file) {
1484  file = backup_file;
1485  backup_file = NULL;
1486  } else {
1487  break;
1488  }
1489  }
1490 
1491  if (!switch_test_flag(fh, SWITCH_FILE_OPEN)) {
1493  status = SWITCH_STATUS_NOTFOUND;
1494  continue;
1495  }
1496 
1497  switch_channel_audio_sync(channel);
1499  switch_channel_set_private(channel, "__fh", fh);
1501 
1504  }
1505 
1506  if (!abuf) {
1507  write_frame.buflen = FILE_STARTSAMPLES * sizeof(*abuf) * fh->channels;
1508  switch_zmalloc(abuf, write_frame.buflen);
1509  write_frame.data = abuf;
1510  }
1511 
1512  if (sample_start > 0) {
1513  uint32_t pos = 0;
1514  switch_core_file_seek(fh, &pos, 0, SEEK_SET);
1515  switch_core_file_seek(fh, &pos, sample_start, SEEK_CUR);
1517  }
1518 
1520  //title = switch_core_session_strdup(session, p);
1521  switch_channel_set_variable(channel, "RECORD_TITLE", p);
1522  }
1523 
1525  //copyright = switch_core_session_strdup(session, p);
1526  switch_channel_set_variable(channel, "RECORD_COPYRIGHT", p);
1527  }
1528 
1530  //software = switch_core_session_strdup(session, p);
1531  switch_channel_set_variable(channel, "RECORD_SOFTWARE", p);
1532  }
1533 
1535  //artist = switch_core_session_strdup(session, p);
1536  switch_channel_set_variable(channel, "RECORD_ARTIST", p);
1537  }
1538 
1540  //comment = switch_core_session_strdup(session, p);
1541  switch_channel_set_variable(channel, "RECORD_COMMENT", p);
1542  }
1543 
1545  //date = switch_core_session_strdup(session, p);
1546  switch_channel_set_variable(channel, "RECORD_DATE", p);
1547  }
1548 
1549  interval = read_impl.microseconds_per_packet / 1000;
1550 
1551  codec_name = "L16";
1552 
1553  if (!switch_core_codec_ready((&codec))) {
1554  if (switch_core_codec_init(&codec,
1555  codec_name,
1556  NULL,
1557  NULL,
1558  fh->samplerate,
1559  interval, read_impl.number_of_channels,
1562  SWITCH_LOG_DEBUG, "Codec Activated %s@%uhz %u channels %dms\n",
1563  codec_name, fh->samplerate, read_impl.number_of_channels, interval);
1564 
1565 
1566  } else {
1568  "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name,
1569  fh->samplerate, read_impl.number_of_channels, interval);
1571  switch_channel_set_private(channel, "__fh", NULL);
1573 
1575 
1577 
1579  status = SWITCH_STATUS_GENERR;
1580  continue;
1581  }
1582  }
1583 
1584  test_native = switch_test_flag(fh, SWITCH_FILE_NATIVE);
1585 
1586  if (test_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));
1593 
1595  switch_channel_set_private(channel, "__fh", NULL);
1597 
1600 
1602  status = SWITCH_STATUS_GENERR;
1603  continue;
1604 
1605  }
1606  } else {
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;
1611  }
1612 
1613  last_native = test_native;
1614 
1615  if (timer_name && !timer.samplecount) {
1616  uint32_t len;
1617 
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);
1623  switch_channel_set_private(channel, "__fh", NULL);
1625 
1627 
1630  status = SWITCH_STATUS_GENERR;
1631  continue;
1632  }
1633  switch_core_timer_sync(&timer); // Sync timer
1635  "Setup timer success %u bytes per %d ms! %d ch\n", len, interval, codec.implementation->number_of_channels);
1636  }
1637  write_frame.rate = fh->samplerate;
1638  write_frame.channels = fh->channels;
1639  if (timer_name) {
1640  /* start a thread to absorb incoming audio */
1641  switch_core_service_session(session);
1642  }
1643 
1644  ilen = samples * channels;
1645 
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");
1650  }
1651  if (!strncasecmp(file, "tone_stream:", 12)) {
1652  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Type", "tone_stream");
1653  }
1654  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Path", file);
1655  if (fh->params) {
1656  switch_event_merge(event, fh->params);
1657  }
1658  switch_event_fire(&event);
1659  }
1660 
1661  if (!fh->audio_buffer) {
1664  }
1665 
1666  for (;;) {
1667  int do_speed = 1;
1668  int f;
1669 
1670  if (!switch_channel_ready(channel)) {
1671  status = SWITCH_STATUS_FALSE;
1672  break;
1673  }
1674 
1675  if ((f = switch_channel_test_flag(channel, CF_BREAK))) {
1677  if (f == 2) {
1678  done = 1;
1679  }
1680  status = SWITCH_STATUS_BREAK;
1681  break;
1682  }
1683 
1684  switch_ivr_parse_all_events(session);
1685 
1686  if (args) {
1687  /*
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.
1690  */
1691  if (switch_channel_has_dtmf(channel)) {
1692  switch_channel_dequeue_dtmf(channel, &dtmf);
1693 
1694  if (!args->input_callback && !args->buf && !args->dmachine) {
1695  status = SWITCH_STATUS_BREAK;
1696  done = 1;
1697  break;
1698  }
1699 
1700 
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) {
1704  break;
1705  }
1706  }
1707 
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;
1713  }
1714  }
1715 
1716  if (args->input_callback) {
1717  switch_event_t *event;
1718 
1720  switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
1721  if (ostatus != SWITCH_STATUS_SUCCESS) {
1722  status = ostatus;
1723  }
1724 
1725  switch_event_destroy(&event);
1726  }
1727  }
1728 
1729  if (status != SWITCH_STATUS_SUCCESS) {
1730  done = 1;
1731  break;
1732  }
1733  }
1734 
1735  buflen = FILE_STARTSAMPLES * sizeof(*abuf) * (fh->cur_channels > 0 ? fh->cur_channels : fh->channels);
1736 
1737  if (buflen > write_frame.buflen) {
1738  abuf = realloc(abuf, buflen);
1739  write_frame.data = abuf;
1740  write_frame.buflen = buflen;
1741  }
1742 
1744  if (framelen > FILE_STARTSAMPLES) {
1745  framelen = FILE_STARTSAMPLES;
1746  }
1747  memset(abuf, 255, framelen);
1748  olen = ilen;
1749  do_speed = 0;
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))) {
1752  if (eof) {
1753  break;
1754  } else {
1755  continue;
1756  }
1757  }
1758 
1759  if (bread < framelen) {
1760  memset(abuf + bread, 255, framelen - bread);
1761  }
1762 
1763  olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
1764  do_speed = 0;
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))) {
1767  if (eof) {
1768  break;
1769  } else {
1770  continue;
1771  }
1772  }
1773 
1774  fh->offset_pos += (uint32_t)(switch_test_flag(fh, SWITCH_FILE_NATIVE) ? bread : bread / 2);
1775 
1776  if (bread < framelen) {
1777  memset(abuf + bread, 255, framelen - bread);
1778  }
1779 
1780  olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
1781  } else {
1782  switch_status_t rstatus;
1783 
1784  if (eof) {
1785  break;
1786  }
1787  olen = FILE_STARTSAMPLES;
1789  olen /= 2;
1790  }
1792 
1793  if ((rstatus = switch_core_file_read(fh, abuf, &olen)) == SWITCH_STATUS_BREAK) {
1794  continue;
1795  }
1796 
1797  if (rstatus != SWITCH_STATUS_SUCCESS) {
1798  eof++;
1799  continue;
1800  }
1801 
1802  test_native = switch_test_flag(fh, SWITCH_FILE_NATIVE);
1803 
1804  if (test_native != last_native) {
1805  if (test_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));
1810  eof++;
1811  continue;
1812  }
1813  } else {
1814  write_frame.codec = &codec;
1815  framelen = codec.implementation->decoded_bytes_per_packet;
1816  }
1818  }
1819 
1820  last_native = test_native;
1821 
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);
1825 
1827  olen /= 2;
1828  }
1829 
1830  }
1831 
1832  if (done || olen <= 0) {
1833  break;
1834  }
1835 
1837  if (fh->speed > 2) {
1838  fh->speed = 2;
1839  } else if (fh->speed < -2) {
1840  fh->speed = -2;
1841  }
1842  }
1843 
1844  if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->audio_buffer && last_speed > -1 && last_speed != fh->speed) {
1846  }
1847 
1849  /* file position has changed flush the buffer */
1852  }
1853 
1854 
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;
1860 
1861  supplement = (int) (factor * olen);
1862  if (!supplement) {
1863  supplement = 1;
1864  }
1865  newlen = (fh->speed > 0) ? olen - supplement : olen + supplement;
1866 
1867  step = (fh->speed > 0) ? (newlen / supplement) : (olen / supplement);
1868 
1869  if (!fh->sp_audio_buffer) {
1870  switch_buffer_create_dynamic(&fh->sp_audio_buffer, 1024, 1024, 0);
1871  }
1872 
1873  while ((wrote + step) < newlen) {
1874  switch_buffer_write(fh->sp_audio_buffer, bp, step * 2);
1875  wrote += step;
1876  bp += step;
1877  if (fh->speed > 0) {
1878  bp++;
1879  } else {
1880  float f;
1881  short s;
1882  f = (float) (*bp + *(bp + 1) + *(bp - 1));
1883  f /= 3;
1884  s = (short) f;
1886  wrote++;
1887  }
1888  }
1889  if (wrote < newlen) {
1890  switch_size_t r = newlen - wrote;
1891  switch_buffer_write(fh->sp_audio_buffer, bp, r * 2);
1892  }
1893  last_speed = fh->speed;
1894  continue;
1895  }
1896 
1897  if (olen < llen) {
1898  uint8_t *dp = (uint8_t *) write_frame.data;
1899  memset(dp + (int) olen, 255, (int) (llen - olen));
1900  olen = llen;
1901  }
1902 
1903  if (!more_data) {
1904  if (timer_name) {
1906  break;
1907  }
1908  } else { /* time off the channel (if you must) */
1909  switch_frame_t *read_frame;
1910  switch_status_t tstatus;
1911 
1912  while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
1914  switch_yield(10000);
1915  }
1916 
1917  tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_SINGLE_READ, 0);
1918 
1919 
1920  if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
1921  break;
1922  }
1923 
1924  if (args && args->dmachine) {
1925  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
1926  break;
1927  }
1928  }
1929 
1930  if (args && (args->read_frame_callback)) {
1931  int ok = 1;
1933  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
1934  ok = 0;
1935  }
1937  if (!ok) {
1938  break;
1939  }
1940  }
1941  }
1942  }
1943 
1944  more_data = 0;
1945  write_frame.samples = (uint32_t) olen;
1946 
1948  write_frame.datalen = (uint32_t) olen;
1949  } else {
1950  write_frame.datalen = write_frame.samples * 2;
1951  }
1952 
1953  llen = olen;
1954 
1955  if (timer_name) {
1956  write_frame.timestamp = timer.samplecount;
1957  }
1958 #ifndef WIN32
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);
1962  }
1963 #endif
1964 #endif
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);
1970  }
1971  }
1972 
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);
1976  }
1977 
1978  status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
1979 
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;
1987  } else {
1988  status = SWITCH_STATUS_TIMEOUT;
1989  }
1990  done = 1;
1991  break;
1992  }
1993  }
1994 
1995 
1996  if (status == SWITCH_STATUS_MORE_DATA) {
1997  status = SWITCH_STATUS_SUCCESS;
1998  more_data = 1;
1999  continue;
2000  } else if (status != SWITCH_STATUS_SUCCESS) {
2001  done = 1;
2002  break;
2003  }
2004 
2005  if (done) {
2006  break;
2007  }
2008  }
2009 
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);
2012 
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));
2016  }
2017 
2018  switch_channel_set_variable_printf(channel, "playback_samples", "%d", fh->samples_in);
2019 
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");
2024  }
2025  if (!strncasecmp(file, "tone_stream:", 12)) {
2026  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Type", "tone_stream");
2027  }
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");
2031  } else {
2032  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-Status", "done");
2033  }
2034  if (fh->params) {
2035  switch_event_merge(event, fh->params);
2036  }
2037  switch_event_fire(&event);
2038  }
2039 
2041  switch_channel_set_private(channel, "__fh", NULL);
2043 
2046 
2047  if (fh->audio_buffer) {
2049  }
2050 
2051  if (fh->sp_audio_buffer) {
2053  }
2054  }
2055 
2056  if (switch_core_codec_ready((&codec))) {
2057  switch_core_codec_destroy(&codec);
2058  }
2059 
2060  if (timer.samplecount) {
2061  /* End the audio absorbing thread */
2063  switch_core_timer_destroy(&timer);
2064  }
2065 
2066  switch_safe_free(abuf);
2067 
2069 
2071 
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);
2074  }
2075 
2076 
2077  return status;
2078 }
2079 
2081  uint32_t silence_hits, uint32_t listen_hits, uint32_t timeout_ms, const char *file)
2082 {
2083  uint32_t score, count = 0, j = 0;
2084  double energy = 0;
2086  int divisor = 0;
2087  uint32_t org_silence_hits = silence_hits;
2088  uint32_t channels;
2089  switch_frame_t *read_frame;
2091  int16_t *data;
2092  uint32_t listening = 0;
2093  int countdown = 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);
2101 
2102 
2103  if (timeout_ms) {
2104  sample_count = (read_impl.actual_samples_per_second / 1000) * timeout_ms;
2105  }
2106 
2107  if (file) {
2108  if (switch_core_file_open(&fh,
2109  file,
2110  read_impl.number_of_channels,
2112  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failure opening playback file %s.\n", file);
2114  return SWITCH_STATUS_NOTFOUND;
2115  }
2117  write_frame.data = abuf;
2118  write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
2119  }
2120 
2121 
2122  if (switch_core_codec_init(&raw_codec,
2123  "L16",
2124  NULL,
2125  NULL,
2126  read_impl.actual_samples_per_second,
2127  read_impl.microseconds_per_packet / 1000,
2130 
2131  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to initialize L16 codec.\n");
2132  status = SWITCH_STATUS_FALSE;
2133  goto end;
2134  }
2135 
2136  write_frame.codec = &raw_codec;
2137 
2138  divisor = read_impl.actual_samples_per_second / 8000;
2139  channels = read_impl.number_of_channels;
2140 
2141  switch_core_session_set_read_codec(session, &raw_codec);
2142 
2143  while (switch_channel_ready(channel)) {
2144 
2145  /* reinitialize energy value per loop */
2146  energy = 0;
2147 
2148  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2149 
2150  if (!SWITCH_READ_ACCEPTABLE(status)) {
2151  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to read frame.\n");
2152  break;
2153  }
2154 
2155  if (sample_count) {
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);
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);
2164  break;
2165  }
2166  }
2167 
2168  if (abuf) {
2170 
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);
2173  break;
2174  }
2175 
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);
2180  break;
2181  }
2182  }
2183 
2184  if (countdown) {
2185  if (!--countdown) {
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");
2190  break;
2191  } else {
2192  continue;
2193  }
2194  }
2195 
2196  data = (int16_t *) read_frame->data;
2197 
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++]);
2202  j += channels;
2203  }
2204  }
2205 
2206  score = (uint32_t) (energy / (read_frame->samples / divisor));
2207 
2208  if (score >= thresh) {
2209  listening++;
2210  }
2211 
2212  if (((listen_hits == 0) || (listening > listen_hits)) && (score < thresh)) {
2213  if (!--silence_hits) {
2214  countdown = 25;
2215  }
2216  } else {
2217  silence_hits = org_silence_hits;
2218  }
2219  }
2220 
2222  switch_core_codec_destroy(&raw_codec);
2223 
2224  end:
2225 
2226  if (abuf) {
2227 
2229  free(abuf);
2230  }
2231 
2232  return status;
2233 }
2234 
2236  uint32_t audio_hits, uint32_t timeout_ms, const char *file)
2237 {
2238  uint32_t score, count = 0, j = 0;
2239  double energy = 0;
2241  int divisor = 0;
2242  uint32_t channels;
2243  switch_frame_t *read_frame;
2245  int16_t *data;
2246  uint32_t hits = 0;
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);
2254 
2255  if (timeout_ms) {
2256  sample_count = (read_impl.actual_samples_per_second / 1000) * timeout_ms;
2257  }
2258 
2259  if (file) {
2260  if (switch_core_file_open(&fh,
2261  file,
2262  read_impl.number_of_channels,
2264  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failure opening playback file %s.\n", file);
2266  return SWITCH_STATUS_NOTFOUND;
2267  }
2269  write_frame.data = abuf;
2270  write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
2271  }
2272 
2273 
2274  if (switch_core_codec_init(&raw_codec,
2275  "L16",
2276  NULL,
2277  NULL,
2278  read_impl.actual_samples_per_second,
2279  read_impl.microseconds_per_packet / 1000,
2282 
2283  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to initialize L16 codec.\n");
2284  status = SWITCH_STATUS_FALSE;
2285  goto end;
2286  }
2287 
2288  write_frame.codec = &raw_codec;
2289 
2290  divisor = read_impl.actual_samples_per_second / 8000;
2291  channels = read_impl.number_of_channels;
2292 
2293  switch_core_session_set_read_codec(session, &raw_codec);
2294 
2295  while (switch_channel_ready(channel)) {
2296 
2297  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2298 
2299  if (!SWITCH_READ_ACCEPTABLE(status)) {
2300  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to read frame.\n");
2301  break;
2302  }
2303 
2304  if (sample_count) {
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);
2310  "switch_ivr_detect_audio: TIMEOUT after %d ms at %d hits\n",
2311  timeout_ms, hits);
2312  break;
2313  }
2314  }
2315 
2316  if (abuf) {
2318 
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);
2321  break;
2322  }
2323 
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);
2328  break;
2329  }
2330  }
2331 
2332  data = (int16_t *) read_frame->data;
2333 
2334  for (energy = 0, j = 0, count = 0; count < read_frame->samples; count++) {
2335  energy += abs(data[j++]);
2336  j += channels;
2337  }
2338 
2339  score = (uint32_t) (energy / (read_frame->samples / divisor));
2340 
2341  if (score >= thresh) {
2342  hits++;
2343  } else {
2344  hits=0;
2345  }
2346 
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");
2350  break;
2351  }
2352  }
2353 
2355  switch_core_codec_destroy(&raw_codec);
2356 
2357  end:
2358 
2359  if (abuf) {
2360 
2362  free(abuf);
2363  }
2364 
2365  return status;
2366 }
2367 
2369  uint32_t silence_hits, uint32_t timeout_ms, const char *file)
2370 {
2371  uint32_t score, count = 0, j = 0;
2372  double energy = 0;
2374  int divisor = 0;
2375  uint32_t channels;
2376  switch_frame_t *read_frame;
2378  int16_t *data;
2379  uint32_t hits = 0;
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);
2387 
2388 
2389  if (timeout_ms) {
2390  sample_count = (read_impl.actual_samples_per_second / 1000) * timeout_ms;
2391  }
2392 
2393  if (file) {
2394  if (switch_core_file_open(&fh,
2395  file,
2396  read_impl.number_of_channels,
2398  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failure opening playback file %s.\n", file);
2400  return SWITCH_STATUS_NOTFOUND;
2401  }
2403  write_frame.data = abuf;
2404  write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
2405  }
2406 
2407 
2408  if (switch_core_codec_init(&raw_codec,
2409  "L16",
2410  NULL,
2411  NULL,
2412  read_impl.actual_samples_per_second,
2413  read_impl.microseconds_per_packet / 1000,
2416 
2417  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to initialize L16 codec.\n");
2418  status = SWITCH_STATUS_FALSE;
2419  goto end;
2420  }
2421 
2422  write_frame.codec = &raw_codec;
2423 
2424  divisor = read_impl.actual_samples_per_second / 8000;
2425  channels = read_impl.number_of_channels;
2426 
2427  switch_core_session_set_read_codec(session, &raw_codec);
2428 
2429  while (switch_channel_ready(channel)) {
2430 
2431  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2432 
2433  if (!SWITCH_READ_ACCEPTABLE(status)) {
2434  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to read frame.\n");
2435  break;
2436  }
2437 
2438  if (sample_count) {
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);
2444  "switch_ivr_detect_silence: TIMEOUT after %d ms at %d hits\n",
2445  timeout_ms, hits);
2446  break;
2447  }
2448  }
2449 
2450  if (abuf) {
2452 
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);
2455  break;
2456  }
2457 
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);
2462  break;
2463  }
2464  }
2465 
2466  data = (int16_t *) read_frame->data;
2467 
2468  for (energy = 0, j = 0, count = 0; count < read_frame->samples; count++) {
2469  energy += abs(data[j++]);
2470  j += channels;
2471  }
2472 
2473  score = (uint32_t) (energy / (read_frame->samples / divisor));
2474 
2475  if (score <= thresh) {
2476  hits++;
2477  } else {
2478  hits=0;
2479  }
2480 
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");
2484  break;
2485  }
2486  }
2487 
2489  switch_core_codec_destroy(&raw_codec);
2490 
2491  end:
2492 
2493  if (abuf) {
2494 
2496  free(abuf);
2497  }
2498 
2499  return status;
2500 }
2501 
2503  uint32_t min_digits,
2504  uint32_t max_digits,
2505  const char *prompt_audio_file,
2506  const char *var_name,
2507  char *digit_buffer,
2508  switch_size_t digit_buffer_length,
2509  uint32_t timeout,
2510  const char *valid_terminators,
2511  uint32_t digit_timeout)
2512 
2513 {
2514  switch_channel_t *channel;
2515  switch_input_args_t args = { 0 };
2517  size_t len = 0;
2518  char tb[2] = "";
2519  int term_required = 0;
2520 
2521 
2522  if (valid_terminators && *valid_terminators == '=') {
2523  term_required = 1;
2524  }
2525 
2526  switch_assert(session);
2527 
2528  if (!digit_timeout) {
2529  digit_timeout = timeout;
2530  }
2531 
2532  if (max_digits < min_digits) {
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;
2536  }
2537 
2538  channel = switch_core_session_get_channel(session);
2540 
2541  if (var_name) {
2542  switch_channel_set_variable(channel, var_name, NULL);
2543  }
2544 
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;
2548  }
2549 
2551  return SWITCH_STATUS_FALSE;
2552  }
2553 
2554  memset(digit_buffer, 0, digit_buffer_length);
2555  args.buf = digit_buffer;
2556  args.buflen = (uint32_t) digit_buffer_length;
2557 
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;
2561  }
2562  }
2563 
2564  if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
2565  goto end;
2566  }
2567 
2568  len = strlen(digit_buffer);
2569 
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);
2575  }
2576 
2577 
2578  if (tb[0]) {
2579  char *p;
2580 
2582 
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;
2588  }
2589  }
2590  }
2591  } else if (term_required) {
2592  status = SWITCH_STATUS_TOO_SMALL;
2593  }
2594 
2595  len = strlen(digit_buffer);
2596  if ((min_digits && len < min_digits)) {
2597  status = SWITCH_STATUS_TOO_SMALL;
2598  }
2599 
2600  switch (status) {
2601  case SWITCH_STATUS_SUCCESS:
2603  break;
2604  case SWITCH_STATUS_TIMEOUT:
2606  break;
2607  default:
2609  break;
2610 
2611  }
2612 
2613  end:
2614 
2615  if (status != SWITCH_STATUS_RESTART && max_digits == 1 && len == 1 && valid_terminators && strchr(valid_terminators, *digit_buffer)) {
2616  *digit_buffer = '\0';
2617  }
2618 
2619  if (var_name && !zstr(digit_buffer)) {
2620  switch_channel_set_variable(channel, var_name, digit_buffer);
2621  }
2622 
2623  return status;
2624 
2625 }
2626 
2628  uint32_t min_digits,
2629  uint32_t max_digits,
2630  uint32_t max_tries,
2631  uint32_t timeout,
2632  const char *valid_terminators,
2633  const char *prompt_audio_file,
2634  const char *bad_input_audio_file,
2635  const char *var_name,
2636  char *digit_buffer,
2637  uint32_t digit_buffer_length,
2638  const char *digits_regex,
2639  uint32_t digit_timeout,
2640  const char *transfer_on_failure)
2641 {
2643  char *var_name_invalid = NULL;
2644 
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);
2649  }
2650 
2651  while (switch_channel_ready(channel) && max_tries) {
2652  switch_status_t status;
2653 
2654  memset(digit_buffer, 0, digit_buffer_length);
2655 
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);
2658 
2659  if (status == SWITCH_STATUS_RESTART) {
2660  return status;
2661  }
2662 
2663  if (status == SWITCH_STATUS_TIMEOUT && strlen(digit_buffer) >= min_digits) {
2664  status = SWITCH_STATUS_SUCCESS;
2665  }
2666 
2667  if ((min_digits == 0) && (strlen(digit_buffer) == 0) && switch_channel_get_variable(channel, SWITCH_READ_TERMINATOR_USED_VARIABLE) != 0)
2668  {
2669  return SWITCH_STATUS_SUCCESS;
2670  }
2671 
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;
2677  }
2678  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "Test Regex [%s][%s]\n", digit_buffer, digits_regex);
2679 
2680  if (switch_regex_match(digit_buffer, digits_regex) == SWITCH_STATUS_SUCCESS) {
2681  return SWITCH_STATUS_SUCCESS;
2682  } else {
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);
2688  }
2689  }
2690  }
2691  }
2692  }
2693 
2694  if (!switch_channel_ready(channel)) {
2695  break;
2696  }
2697 
2698  switch_ivr_play_file(session, NULL, bad_input_audio_file, NULL);
2699  max_tries--;
2700  }
2701 
2702  memset(digit_buffer, 0, digit_buffer_length);
2703 
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 */
2706 
2707  if (!zstr(transfer_on_failure)) {
2708  const char *failure_ext = NULL;
2709  const char *failure_dialplan = NULL;
2710  const char *failure_context = NULL;
2711  char *target[4];
2712  char *mydata = switch_core_session_strdup(session, transfer_on_failure);
2713  int argc;
2714 
2715  argc = switch_separate_string(mydata, ' ', target, (sizeof(target) / sizeof(target[0])));
2716 
2717  if ( argc < 1 ) {
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;
2720  }
2721 
2722  if ( argc > 0 ) {
2723  failure_ext = target[0];
2724  }
2725 
2726  if ( argc > 1 ) {
2727  failure_dialplan = target[1];
2728  }
2729 
2730  if ( argc > 2 ) {
2731  failure_context = target[2];
2732  }
2733 
2735  "PAGD failure! Transfer to: %s / %s / %s\n", failure_ext, failure_dialplan, failure_context);
2736 
2737  switch_ivr_session_transfer(session,failure_ext, failure_dialplan, failure_context);
2738  return SWITCH_STATUS_FALSE;
2739  }
2740 
2741  return SWITCH_STATUS_FALSE;
2742 }
2743 
2746  switch_codec_t *codec, switch_timer_t *timer, const char *text, switch_input_args_t *args)
2747 {
2749  short abuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
2750  switch_dtmf_t dtmf = { 0 };
2751  uint32_t len = 0;
2752  switch_size_t ilen = 0;
2753  switch_frame_t write_frame = { 0 };
2756  switch_size_t extra = 0;
2757  char *tmp = NULL;
2758  const char *star, *pound, *p;
2759  switch_size_t starlen, poundlen;
2760 
2761  if (!sh) {
2762  return SWITCH_STATUS_FALSE;
2763  }
2764 
2766  return SWITCH_STATUS_FALSE;
2767  }
2768 
2769  if (!switch_core_codec_ready(codec)) {
2770  return SWITCH_STATUS_FALSE;
2771  }
2772 
2774 
2775  write_frame.data = abuf;
2776  write_frame.buflen = sizeof(abuf);
2777 
2778  len = sh->samples * 2 * sh->channels;
2779 
2780  flags = 0;
2781 
2782  if (!(star = switch_channel_get_variable(channel, "star_replace"))) {
2783  star = "star";
2784  }
2785  if (!(pound = switch_channel_get_variable(channel, "pound_replace"))) {
2786  pound = "pound";
2787  }
2788  starlen = strlen(star);
2789  poundlen = strlen(pound);
2790 
2791 
2792  for (p = text; p && *p; p++) {
2793  if (*p == '*') {
2794  extra += starlen;
2795  } else if (*p == '#') {
2796  extra += poundlen;
2797  }
2798  }
2799 
2800  if (extra) {
2801  char *tp;
2802  switch_size_t mylen = strlen(text) + extra + 1;
2803  tmp = malloc(mylen);
2804  if (!tmp) {
2806  return SWITCH_STATUS_MEMERR;
2807  }
2808  memset(tmp, 0, mylen);
2809  tp = tmp;
2810  for (p = text; p && *p; p++) {
2811  if (*p == '*' ) {
2812  snprintf(tp + strlen(tp), sizeof(tp) - strlen(tp), "%s", star);
2813  tp += starlen;
2814  } else if (*p == '#') {
2815  snprintf(tp + strlen(tp), sizeof(tp) - strlen(tp), "%s", pound);
2816  tp += poundlen;
2817  } else {
2818  *tp++ = *p;
2819  }
2820  }
2821 
2822  text = tmp;
2823  }
2824 
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);
2828  text = NULL;
2829 
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;
2835 
2836  switch_assert(codec->implementation != NULL);
2837 
2838  switch_channel_audio_sync(channel);
2839 
2840 
2841  for (;;) {
2842  switch_event_t *event;
2843 
2844  ilen = len;
2845 
2846  if (!switch_channel_ready(channel)) {
2847  status = SWITCH_STATUS_FALSE;
2848  break;
2849  }
2850 
2851  if (switch_channel_test_flag(channel, CF_BREAK)) {
2853  status = SWITCH_STATUS_BREAK;
2854  break;
2855  }
2856 
2857  switch_ivr_parse_all_events(session);
2858 
2859  if (args) {
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.
2862  */
2863  if (switch_channel_has_dtmf(channel)) {
2864  if (!args->input_callback && !args->buf && !args->dmachine) {
2865  status = SWITCH_STATUS_BREAK;
2866  break;
2867  }
2868  if (args->buf && !strcasecmp(args->buf, "_break_")) {
2869  status = SWITCH_STATUS_BREAK;
2870  } else {
2871  switch_channel_dequeue_dtmf(channel, &dtmf);
2872 
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) {
2876  break;
2877  }
2878  }
2879 
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;
2885  }
2886  }
2887  }
2888 
2889  if (args->input_callback) {
2891  switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
2892  if (ostatus != SWITCH_STATUS_SUCCESS) {
2893  status = ostatus;
2894  }
2895  switch_event_destroy(&event);
2896  }
2897  }
2898 
2899  if (status != SWITCH_STATUS_SUCCESS) {
2900  break;
2901  }
2902  }
2903 
2905  if (timer) {
2907  break;
2908  }
2909  } else {
2910  switch_frame_t *read_frame;
2911  switch_status_t tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2912 
2913  while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
2915  switch_yield(10000);
2916  }
2917 
2918  if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
2919  break;
2920  }
2921 
2922  if (args && args->dmachine) {
2923  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
2924  goto done;
2925  }
2926  }
2927 
2928  if (args && (args->read_frame_callback)) {
2929  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
2930  goto done;
2931  }
2932  }
2933  }
2934  continue;
2935  }
2936 
2937 
2939  status = switch_core_speech_read_tts(sh, abuf, &ilen, &flags);
2940 
2941  if (status != SWITCH_STATUS_SUCCESS) {
2942  if (status == SWITCH_STATUS_BREAK) {
2943  status = SWITCH_STATUS_SUCCESS;
2944  }
2945  break;
2946  }
2947 
2948  write_frame.datalen = (uint32_t) ilen;
2949  write_frame.samples = (uint32_t) (ilen / 2 / sh->channels);
2950  if (timer) {
2951  write_frame.timestamp = timer->samplecount;
2952  }
2954  break;
2955  }
2956 
2957  if (timer) {
2959  break;
2960  }
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);
2964 
2965  while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
2967  switch_yield(10000);
2968  }
2969 
2970  if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
2971  break;
2972  }
2973 
2974  if (args && args->dmachine) {
2975  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
2976  goto done;
2977  }
2978  }
2979 
2980  if (args && (args->read_frame_callback)) {
2981  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
2982  goto done;
2983  }
2984  }
2985  }
2986  }
2987 
2988  done:
2989 
2990  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "done speaking text\n");
2991  flags = 0;
2993 
2995  return status;
2996 }
2997 
2999  char tts_name[80];
3000  char voice_name[80];
3004 };
3005 
3007 
3009 {
3010  cached_speech_handle_t *cache_obj = NULL;
3012 
3015  if (cache_obj->timer.interval) {
3016  switch_core_timer_destroy(&cache_obj->timer);
3017  }
3018  if (cache_obj->sh.speech_interface) {
3019  switch_core_speech_close(&cache_obj->sh, &flags);
3020  }
3021  switch_core_codec_destroy(&cache_obj->codec);
3023  }
3024 }
3025 
3027  const char *tts_name, const char *voice_name, const char *text, switch_input_args_t *args)
3028 {
3030  uint32_t rate = 0;
3031  int interval = 0;
3032  uint32_t channels;
3033  switch_frame_t write_frame = { 0 };
3034  switch_timer_t ltimer, *timer;
3035  switch_codec_t lcodec, *codec;
3037  char *codec_name;
3039  switch_speech_handle_t lsh, *sh;
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);
3046 
3048  return SWITCH_STATUS_FALSE;
3049  }
3050 
3052 
3053  sh = &lsh;
3054  codec = &lcodec;
3055  timer = &ltimer;
3056 
3059  need_create = 0;
3060  if (!strcasecmp(cache_obj->tts_name, tts_name)) {
3061  need_alloc = 0;
3062  } else {
3064  }
3065  }
3066 
3067  if (!cache_obj) {
3068  cache_obj = (cached_speech_handle_t *) switch_core_session_alloc(session, sizeof(*cache_obj));
3069  }
3070  if (need_alloc) {
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));
3074  }
3075  sh = &cache_obj->sh;
3076  codec = &cache_obj->codec;
3077  timer = &cache_obj->timer;
3078  }
3079 
3080  timer_name = switch_channel_get_variable(channel, "timer_name");
3081 
3083 
3084  rate = read_impl.actual_samples_per_second;
3085  interval = read_impl.microseconds_per_packet / 1000;
3086  channels = read_impl.number_of_channels;
3087 
3088  if (need_create) {
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);
3095  return status;
3096  }
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);
3100  }
3101 
3103  flags = 0;
3104  switch_core_speech_close(sh, &flags);
3106  return SWITCH_STATUS_FALSE;
3107  }
3108  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "OPEN TTS %s\n", tts_name);
3109 
3110  codec_name = "L16";
3111 
3112  if (need_create) {
3113  if (switch_core_codec_init(codec,
3114  codec_name,
3115  NULL,
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");
3119  } else {
3120  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed %s@%uhz 1 channel %dms\n", codec_name,
3121  rate, interval);
3122  flags = 0;
3123  switch_core_speech_close(sh, &flags);
3127  return SWITCH_STATUS_GENERR;
3128  }
3129  }
3130 
3131  write_frame.codec = codec;
3132 
3133  if (timer_name) {
3134  if (need_create) {
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);
3138  flags = 0;
3139  switch_core_speech_close(sh, &flags);
3143  return SWITCH_STATUS_GENERR;
3144  }
3145  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setup timer success %u bytes per %d ms!\n", sh->samples * 2,
3146  interval);
3147  }
3148  switch_core_timer_sync(timer); // Sync timer
3149 
3150  /* start a thread to absorb incoming audio */
3151  switch_core_service_session(session);
3152 
3153  }
3154 
3155  status = switch_ivr_speak_text_handle(session, sh, write_frame.codec, timer_name ? timer : NULL, text, args);
3156  flags = 0;
3157 
3158  if (!cache_obj) {
3159  switch_core_speech_close(sh, &flags);
3161  }
3162 
3163  if (timer_name) {
3164  /* End the audio absorbing thread */
3166  if (!cache_obj) {
3168  }
3169  }
3170 
3173 
3174  return status;
3175 }
3176 
3177 
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)
3179 {
3180  char *stop_key = (char *) buf;
3181 
3182  switch (itype) {
3184  {
3185  switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
3186  if (dtmf->digit == *stop_key) {
3187  return SWITCH_STATUS_BREAK;
3188  }
3189  }
3190  break;
3191  default:
3192  break;
3193  }
3194 
3195  return SWITCH_STATUS_SUCCESS;
3196 }
3197 
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)
3199 {
3200  switch_channel_t *channel, *other_channel;
3201  switch_core_session_t *other_session;
3202  const char *other_uuid, *moh = NULL;
3203  int moh_br = 0;
3204  switch_input_args_t args = { 0 };
3205  switch_status_t res;
3206 
3208  args.buf = (void *) unhold_key;
3209  args.buflen = (uint32_t) strlen(unhold_key);
3210 
3211  switch_assert(session != NULL);
3212  channel = switch_core_session_get_channel(session);
3213  switch_assert(channel != NULL);
3214 
3215  if ((other_uuid = switch_channel_get_partner_uuid(channel))) {
3216  if ((other_session = switch_core_session_locate(other_uuid))) {
3217  other_channel = switch_core_session_get_channel(other_session);
3218 
3219  if (moh_b) {
3220  moh = moh_b;
3221  } else {
3222  moh = switch_channel_get_hold_music(other_channel);
3223  }
3224 
3225  if (!zstr(moh) && strcasecmp(moh, "silence") && !switch_channel_test_flag(other_channel, CF_BROADCAST)) {
3226  switch_ivr_broadcast(other_uuid, moh, SMF_ECHO_ALEG | SMF_LOOP);
3227  moh_br++;
3228  }
3229 
3230  if (moh_a) {
3231  moh = moh_a;
3232  } else {
3233  moh = switch_channel_get_hold_music(channel);
3234  }
3235 
3236  if (!zstr(moh) && strcasecmp(moh, "silence")) {
3237  res = switch_ivr_play_file(session, NULL, moh, &args);
3238  } else {
3239  res = switch_ivr_collect_digits_callback(session, &args, 0, 0);
3240  }
3241 
3242  (void)res;
3243 
3244  if (moh_br) {
3245  switch_channel_stop_broadcast(other_channel);
3246  }
3247 
3248  switch_core_session_rwunlock(other_session);
3249 
3250 
3251  return SWITCH_STATUS_SUCCESS;
3252  }
3253  }
3254 
3255  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Channel %s is not in a bridge\n", switch_channel_get_name(channel));
3256 
3257  return SWITCH_STATUS_FALSE;
3258 
3259 }
3260 
3261 
3262 
3263 typedef enum {
3264  /** playing initial prompt - allow barge in */
3266  /** looking for speech input */
3268  /** finished looking for speech input */
3270  /** looking for digits */
3272  /** finished looking for digits */
3275 
3276 typedef struct {
3277  int flags;
3279  char *digits;
3282  const char *terminators;
3288 
3290 {
3291  if (args && args->input_callback) {
3292  args->input_callback(session, (void *)event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
3293  }
3294 }
3295 
3296 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)
3297 {
3300 
3302  const char *speech_type = NULL;
3303  switch_event_t *event = (switch_event_t *)input;
3304 
3305  if (event->event_id != SWITCH_EVENT_DETECTED_SPEECH) return SWITCH_STATUS_SUCCESS;
3306 
3307  speech_type = switch_event_get_header(event, "Speech-Type");
3308 
3309  if (zstr(speech_type)) return SWITCH_STATUS_SUCCESS;
3310 
3311  deliver_asr_event(session, event, state->original_args);
3312 
3313  if (!strcasecmp(speech_type, "detected-speech")) {
3314  const char *result = switch_event_get_body(event);
3315 
3316  /* stop waiting for speech */
3318 
3319  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "(%s) DETECTED SPEECH %s\n", switch_channel_get_name(channel), speech_type);
3320 
3321  if (!zstr(result)) {
3322  state->recognition_result = cJSON_Parse(result);
3323 
3324  if (state->recognition_result) {
3325  const char *text = cJSON_GetObjectCstr(state->recognition_result, "text");
3326 
3327  if (!zstr(text)) {
3328  /* stop waiting for digits */
3330  }
3331  }
3332  }
3333  return SWITCH_STATUS_BREAK;
3334  } else if (!strcasecmp(speech_type, "detected-partial-speech")) {
3335  } else if (!strcasecmp("closed", speech_type)) {
3336  /* stop waiting for speech */
3338  return SWITCH_STATUS_BREAK;
3339  } else if (!strcasecmp(speech_type, "begin-speaking")) {
3340  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "(%s) START OF SPEECH\n", switch_channel_get_name(channel));
3341  state->is_speech = SWITCH_TRUE;
3342 
3344  /* barge in on prompt */
3345  return SWITCH_STATUS_BREAK;
3346  }
3347  } else {
3348  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Unhandled Speech-Type %s\n", speech_type);
3349  }
3350  }
3351 
3353  switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
3355  state->is_speech = SWITCH_FALSE;
3356 
3357  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);
3358 
3359  if (!zstr(state->terminators) && strchr(state->terminators, dtmf->digit)) {
3360  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) ACCEPT TERMINATOR %c\n",
3361  switch_channel_get_name(channel), dtmf->digit);
3362 
3363  state->terminator = dtmf->digit;
3364 
3365  /* stop waiting for digits */
3367 
3368  if (switch_test_flag(state, SWITCH_COLLECT_INPUT_DIGITS) && !zstr(state->digits)) {
3369  /* stop waiting for speech */
3371  }
3372 
3373  /* barge-in and break playback on terminator */
3374  return SWITCH_STATUS_BREAK;
3375  }
3376 
3378  int digits_collected = strlen(state->digits);
3379 
3380  if (digits_collected < state->max_digits) {
3381  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) ACCEPT DIGIT %c\n",
3382  switch_channel_get_name(channel), dtmf->digit);
3383  state->digits[digits_collected] = dtmf->digit;
3384  }
3385 
3386  if (digits_collected + 1 >= state->max_digits) {
3387  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) MAX DIGITS COLLECTED\n", switch_channel_get_name(channel));
3388  switch_set_flag(state, SWITCH_COLLECT_INPUT_DIGITS_DONE); // stop waiting for digits
3389  switch_set_flag(state, SWITCH_COLLECT_INPUT_SPEECH_DONE); // stop waiting for speech, too
3390  }
3391  }
3392  return SWITCH_STATUS_BREAK; // got a digit- break for inter-digit timeout / checking results / barge-in
3393  }
3394 
3395  return SWITCH_STATUS_SUCCESS;
3396 }
3397 
3398 
3399 
3400 /*!\brief Play prompt and collect input
3401 *
3402 * Returns collect status
3403 *
3404 * \param[in] session the current session
3405 *
3406 * \return Returns status
3407 * SWITCH_STATUS_SUCCESS when success
3408 * SWITCH_STATUS_FALSE when error
3409 * SWITCH_STATUS_GENERR when error
3410 */
3412  const char *prompt,
3413  const char *recognizer_mod_name,
3414  const char *recognizer_grammar,
3415  int min_digits,
3416  int max_digits,
3417  const char *terminators,
3418  uint32_t digit_timeout,
3419  cJSON **recognition_result,
3420  char **digits_collected,
3421  char *terminator_collected,
3422  switch_input_args_t *args)
3423 {
3425  switch_input_args_t myargs = { 0 };
3428 
3430 
3431  /* configure digit collection */
3432  if (digit_timeout <= 0) digit_timeout = 5000;
3433  if (min_digits < 0) {
3434  min_digits = 0;
3435  }
3436 
3437  /* check if digit collection is enabled */
3438  if (min_digits > 0) {
3439  if (max_digits < min_digits) {
3440  max_digits = min_digits;
3441  }
3442  if (max_digits > 100) {
3443  max_digits = 100;
3444  }
3445  state.digits = switch_core_session_alloc(session, sizeof(char) * (max_digits + 1));
3447  } else {
3449  }
3450 
3451  state.min_digits = min_digits;
3452  state.max_digits = max_digits;
3453  if (!zstr(terminators)) {
3454  if (!strcasecmp(terminators, "any")) {
3455  state.terminators = "1234567890*#";
3456  } else if (!strcasecmp(terminators, "none")) {
3457  state.terminators = NULL;
3458  } else {
3459  state.terminators = terminators;
3460  }
3461  }
3462 
3463  /* start speech recognition, if enabled */
3464  if (recognizer_grammar && recognizer_mod_name) {
3465  if ((status = switch_ivr_detect_speech(session, recognizer_mod_name, recognizer_grammar, "", NULL, NULL)) != SWITCH_STATUS_SUCCESS) {
3466  /* map SWITCH_STATUS_FALSE to SWITCH_STATUS_GENERR to indicate grammar load failed
3467  SWITCH_STATUS_NOT_INITALIZED will be passed back to indicate ASR resource problem */
3468  if (status == SWITCH_STATUS_FALSE) {
3469  status = SWITCH_STATUS_GENERR;
3470  }
3471  goto done;
3472  }
3474  } else {
3476  }
3477 
3478  /* play the prompt, looking for input result */
3479 
3480  if (args) {
3481  state.original_args = args;
3482  myargs.dmachine = args->dmachine;
3484  myargs.user_data = args->user_data;
3485  }
3486 
3488  myargs.buf = &state;
3489  myargs.buflen = sizeof(state);
3490 
3492  status = switch_ivr_play_file(session, NULL, prompt, &myargs);
3494 
3495  if (args && args->dmachine && switch_ivr_dmachine_last_ping(args->dmachine) != SWITCH_STATUS_SUCCESS) {
3498  status = SWITCH_STATUS_SUCCESS;
3499  }
3500 
3501  if (status != SWITCH_STATUS_BREAK && status != SWITCH_STATUS_SUCCESS) {
3502  status = SWITCH_STATUS_FALSE;
3503  goto done;
3504  }
3505 
3506  // wait for final result if not done
3508  int sleep_time = digit_timeout;
3509 
3512  }
3514 
3515  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "(%s) WAITING FOR RESULT\n", switch_channel_get_name(channel));
3516 
3518  && switch_channel_ready(channel)) {
3519 
3520  status = switch_ivr_sleep(session, sleep_time, SWITCH_FALSE, &myargs);
3521 
3522  if (args && args->dmachine && switch_ivr_dmachine_last_ping(args->dmachine) != SWITCH_STATUS_SUCCESS) {
3523  // dmachine done
3524  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) DMACHINE DONE\n", switch_channel_get_name(channel));
3527  status = SWITCH_STATUS_SUCCESS;
3528  goto done;
3529  }
3530 
3531  if (state.terminator != 0) {
3533  status = SWITCH_STATUS_SUCCESS;
3534  sleep_time = digit_timeout;
3535  continue;
3536  }
3537 
3538  if (state.is_speech == SWITCH_FALSE) {
3539 
3540  // calculating how much time has elapsed since the last digit was collected
3541  sleep_time = (switch_micro_time_now() - state.last_digit_time) / 1000;
3542 
3543  if (sleep_time >= digit_timeout) {
3544  // too much time since last digit
3546  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);
3548  } else {
3549  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);
3550  }
3551  status = SWITCH_STATUS_SUCCESS;
3552  sleep_time = digit_timeout;
3553  } else {
3554  // woke up early, sleep for remaining digit timeout
3555  sleep_time = digit_timeout - sleep_time;
3556  }
3557  } else {
3558  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);
3559  }
3560 
3561  if (status != SWITCH_STATUS_BREAK && status != SWITCH_STATUS_SUCCESS) {
3562  // error of some sort
3563  status = SWITCH_STATUS_FALSE;
3564  goto done;
3565  }
3566 
3567  }
3568  }
3569 
3570 done:
3571 
3572  if (status == SWITCH_STATUS_BREAK) {
3573  status = SWITCH_STATUS_SUCCESS;
3574  }
3575 
3578  }
3579 
3580  if (!zstr(state.digits) && strlen(state.digits) >= state.min_digits) {
3581  /* got DTMF result */
3582  if (digits_collected) {
3583  *digits_collected = state.digits;
3584  }
3585 
3586  if (state.recognition_result) {
3587  cJSON_Delete(state.recognition_result);
3588  }
3589  } else if (state.recognition_result) {
3590  /* have some kind of recognition result or error */
3591  if (recognition_result) {
3592  *recognition_result = state.recognition_result;
3593  } else {
3594  cJSON_Delete(state.recognition_result);
3595  }
3596  }
3597 
3598  if (terminator_collected && state.terminator != 0) {
3599  *terminator_collected = state.terminator;
3600  }
3601 
3603 
3604  return status;
3605 }
3606 
3607 
3608 
3609 /* For Emacs:
3610  * Local Variables:
3611  * mode:c
3612  * indent-tabs-mode:t
3613  * tab-width:4
3614  * c-basic-offset:4
3615  * End:
3616  * For VIM:
3617  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
3618  */
switch_status_t switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt,...)
switch_status_t switch_core_speech_read_tts(switch_speech_handle_t *sh, void *data, switch_size_t *datalen, switch_speech_flag_t *flags)
Read rendered audio from the TTS module.
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:311
switch_status_t switch_core_speech_feed_tts(switch_speech_handle_t *sh, const char *text, switch_speech_flag_t *flags)
Feed text to the TTS module.
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:413
void switch_core_thread_session_end(_In_ switch_core_session_t *session)
Signal a thread using a thread session to terminate.
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it&#39;s state machine to end.
#define switch_regex_safe_free(re)
Definition: switch_regex.h:79
#define switch_core_media_gen_key_frame(_session)
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
switch_status_t switch_core_session_io_write_lock(switch_core_session_t *session)
switch_status_t switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix)
A module interface to implement an application.
void switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
switch_status_t switch_core_file_pre_close(_In_ switch_file_handle_t *fh)
Pre close an open file handle, then can get file size etc., no more wirte to the file.
const char * switch_xml_attr_soft(_In_ switch_xml_t xml, _In_z_ const char *attr)
returns the value of the requested tag attribute, or "" if not found
char * switch_core_session_sprintf(_In_ switch_core_session_t *session, _In_z_ _Printf_format_string_ const char *fmt,...)
printf-style style printing routine. The data is output to a string allocated from the session ...
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_say_type_t switch_ivr_get_say_type_by_name(const char *name)
#define switch_event_expand_headers(_event, _in)
Definition: switch_event.h:355
switch_say_type_t type
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700
switch_status_t switch_core_timer_init(switch_timer_t *timer, const char *timer_name, int interval, int samples, switch_memory_pool_t *pool)
Request a timer handle using given time module.
switch_status_t switch_ivr_read(switch_core_session_t *session, uint32_t min_digits, uint32_t max_digits, const char *prompt_audio_file, const char *var_name, char *digit_buffer, switch_size_t digit_buffer_length, uint32_t timeout, const char *valid_terminators, uint32_t digit_timeout)
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
switch_size_t switch_buffer_read(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen)
Read data from a switch_buffer_t up to the ammount of datalen if it is available. Remove read data fr...
switch_xml_t switch_xml_find_child(_In_ switch_xml_t node, _In_z_ const char *childname, _In_opt_z_ const char *attrname, _In_opt_z_ const char *value)
find a child tag in a node called &#39;childname&#39; with an attribute &#39;attrname&#39; which equals &#39;value&#39; ...
switch_status_t switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match)
char * switch_find_end_paren(const char *s, char open, char close)
Definition: switch_utils.c:796
switch_status_t switch_ivr_gentones(switch_core_session_t *session, const char *script, int32_t loops, switch_input_args_t *args)
switch_say_callback_t say_function
switch_status_t switch_ivr_detect_silence(switch_core_session_t *session, uint32_t thresh, uint32_t silence_hits, uint32_t timeout_ms, const char *file)
const char * switch_xml_attr(_In_opt_ switch_xml_t xml, _In_opt_z_ const char *attr)
returns the value of the requested tag attribute, or NULL if not found
switch_status_t switch_channel_execute_on_value(switch_channel_t *channel, const char *variable_value)
static switch_status_t hold_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
switch_status_t switch_play_and_get_digits(switch_core_session_t *session, uint32_t min_digits, uint32_t max_digits, uint32_t max_tries, uint32_t timeout, const char *valid_terminators, const char *prompt_audio_file, const char *bad_input_audio_file, const char *var_name, char *digit_buffer, uint32_t digit_buffer_length, const char *digits_regex, uint32_t digit_timeout, const char *transfer_on_failure)
Play a sound and gather digits with the number of retries specified if the user doesn&#39;t give digits i...
const char * switch_channel_get_partner_uuid(switch_channel_t *channel)
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
void switch_perform_substitution(switch_regex_t *re, int match_count, const char *data, const char *field_data, char *substituted, switch_size_t len, int *ovector)
Definition: switch_regex.c:131
#define switch_core_file_open(_fh, _file_path, _channels, _rate, _flags, _pool)
Open a media file using file format modules.
Definition: switch_core.h:1963
An abstraction to store a tone mapping.
Definition: libteletone.h:93
switch_status_t switch_buffer_create_dynamic(_Out_ switch_buffer_t **buffer, _In_ switch_size_t blocksize, _In_ switch_size_t start_len, _In_ switch_size_t max_len)
Allocate a new dynamic switch_buffer.
switch_status_t switch_ivr_sleep(switch_core_session_t *session, uint32_t ms, switch_bool_t sync, switch_input_args_t *args)
Wait for time to pass for a specified number of milliseconds.
Definition: switch_ivr.c:127
#define switch_channel_stop_broadcast(_channel)
switch_status_t switch_ivr_collect_digits_callback(switch_core_session_t *session, switch_input_args_t *args, uint32_t digit_timeout, uint32_t abs_timeout)
Wait for DTMF digits calling a pluggable callback function when digits are collected.
Definition: switch_ivr.c:1225
uint32_t switch_speech_flag_t
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:590
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
switch_status_t switch_xml_locate_language(switch_xml_t *root, switch_xml_t *node, switch_event_t *params, switch_xml_t *language, switch_xml_t *phrases, switch_xml_t *macros, const char *str_language)
Definition: switch_xml.c:3356
switch_bool_t
Definition: switch_types.h:437
uint32_t timestamp
Definition: switch_frame.h:80
switch_status_t switch_core_session_set_read_codec(_In_ switch_core_session_t *session, switch_codec_t *codec)
Assign the read codec to a given session.
#define SWITCH_URL_SEPARATOR
Definition: switch_types.h:126
switch_status_t switch_core_file_command(switch_file_handle_t *fh, switch_file_command_t command)
switch_status_t switch_core_file_set_string(_In_ switch_file_handle_t *fh, switch_audio_col_t col, const char *string)
Set metadata to the desired string.
switch_status_t switch_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream)
Execute a registered API command.
switch_status_t switch_ivr_broadcast(const char *uuid, const char *path, switch_media_flag_t flags)
Signal the session to broadcast audio.
switch_say_gender_t switch_ivr_get_say_gender_by_name(const char *name)
switch_say_method_t method
switch_memory_pool_t * pool
switch_status_t switch_core_file_get_string(_In_ switch_file_handle_t *fh, switch_audio_col_t col, const char **string)
get metadata of the desired string
Representation of an event.
Definition: switch_event.h:80
switch_status_t switch_core_file_close(_In_ switch_file_handle_t *fh)
Close an open file handle.
#define switch_channel_ready(_channel)
#define arg_recursion_check_stop(_args)
An event Header.
Definition: switch_event.h:65
switch_status_t switch_core_media_set_video_file(switch_core_session_t *session, switch_file_handle_t *fh, switch_rw_t rw)
void switch_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t channels, uint32_t divisor)
Generate static noise.
int teletone_mux_tones(teletone_generation_session_t *ts, teletone_tone_map_t *map)
Execute a single tone generation instruction.
#define switch_channel_media_ready(_channel)
switch_status_t switch_core_file_seek(_In_ switch_file_handle_t *fh, unsigned int *cur_pos, int64_t samples, int whence)
Seek a position in a file.
switch_status_t switch_core_session_exec(_In_ switch_core_session_t *session, _In_ const switch_application_interface_t *application_interface, _In_opt_z_ const char *arg)
Execute an application on a session.
int teletone_destroy_session(teletone_generation_session_t *ts)
Free the buffer allocated by a tone generation session.
switch_bool_t switch_is_number(const char *str)
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, switch_input_args_t *args)
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)
play a file from the disk to the session
A representation of an XML tree.
Definition: switch_xml.h:79
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
switch_status_t switch_core_file_read(_In_ switch_file_handle_t *fh, void *data, switch_size_t *len)
Read media from a file handle.
struct real_pcre switch_regex_t
Definition: switch_regex.h:43
void switch_core_speech_text_param_tts(switch_speech_handle_t *sh, char *param, const char *val)
Set a text parameter on a TTS handle.
switch_status_t switch_ivr_parse_all_events(switch_core_session_t *session)
Parse all commands from an event.
Definition: switch_ivr.c:913
pack cur
Abstract handler to a timer module.
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
switch_size_t switch_buffer_write(_In_ switch_buffer_t *buffer, _In_bytecount_(datalen) const void *data, _In_ switch_size_t datalen)
Write data into a switch_buffer_t up to the length of datalen.
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_input_type_t
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
switch_status_t switch_ivr_speak_text(switch_core_session_t *session, const char *tts_name, const char *voice_name, const char *text, switch_input_args_t *args)
Speak given text with given tts engine.
switch_codec_t * codec
Definition: switch_frame.h:56
uint8_t switch_byte_t
Definition: switch_types.h:256
#define zstr(x)
Definition: switch_utils.h:314
switch_codec_t * switch_core_session_get_read_codec(_In_ switch_core_session_t *session)
Retrieve the read codec from a given session.
switch_status_t switch_ivr_dmachine_last_ping(switch_ivr_dmachine_t *dmachine)
switch_status_t switch_ivr_session_transfer(_In_ switch_core_session_t *session, const char *extension, const char *dialplan, const char *context)
Transfer an existing session to another location.
#define SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME
Definition: switch_types.h:189
switch_status_t switch_core_session_io_read_lock(switch_core_session_t *session)
void switch_change_sln_volume(int16_t *data, uint32_t samples, int32_t vol)
Change the volume of a signed linear audio frame.
switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a frame to a session.
int teletone_run(teletone_generation_session_t *ts, const char *cmd)
Execute a tone generation script and call callbacks after each instruction.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define UNPROTECT_INTERFACE(_it)
switch_status_t switch_core_session_io_rwunlock(switch_core_session_t *session)
#define switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
Definition: switch_utils.h:724
int teletone_init_session(teletone_generation_session_t *ts, int buflen, tone_handler handler, void *user_data)
Initilize a tone generation session.
switch_bool_t switch_ivr_dmachine_is_parsing(switch_ivr_dmachine_t *dmachine)
#define switch_normalize_volume_granular(x)
switch_status_t switch_core_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags)
Close an open speech handle.
uint16_t seq
Definition: switch_frame.h:81
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:124
#define SWITCH_CACHE_SPEECH_HANDLES_VARIABLE
Definition: switch_types.h:188
int64_t switch_time_t
Definition: switch_apr.h:188
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:70
switch_xml_t next
Definition: switch_xml.h:91
static const char * get_recording_var(switch_channel_t *channel, switch_event_t *vars, switch_file_handle_t *fh, const char *name)
switch_status_t switch_ivr_collect_digits_count(switch_core_session_t *session, char *buf, switch_size_t buflen, switch_size_t maxdigits, const char *terminators, char *terminator, uint32_t first_timeout, uint32_t digit_timeout, uint32_t abs_timeout)
Wait for specified number of DTMF digits, untile terminator is received or until the channel hangs up...
Definition: switch_ivr.c:1342
switch_byte_t switch_byte_t * buf
if((uint32_t)(unpack->cur - unpack->buf) > unpack->buflen)
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:998
#define switch_channel_audio_sync(_c)
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
uint32_t datalen
Definition: switch_frame.h:68
const char * switch_channel_get_hold_music(switch_channel_t *channel)
switch_collect_input_flags_t
switch_application_interface_t * switch_loadable_module_get_application_interface(const char *name)
Retrieve the application interface by it&#39;s registered name.
Abstract interface to a say module.
#define SWITCH_READ_RESULT_VARIABLE
Definition: switch_types.h:138
void switch_event_merge(switch_event_t *event, switch_event_t *tomerge)
char * switch_event_get_body(switch_event_t *event)
Retrieve the body value from an event.
Definition: switch_event.c:867
#define switch_core_session_request_video_refresh(_s)
Definition: switch_core.h:2881
void switch_buffer_set_loops(_In_ switch_buffer_t *buffer, _In_ int32_t loops)
Assign a number of loops to read.
uint32_t rate
Definition: switch_frame.h:74
switch_status_t switch_ivr_pause_detect_speech(switch_core_session_t *session)
Pause background Speech detection on a session.
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_channel_dequeue_dtmf(_In_ switch_channel_t *channel, _In_ switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given channel.
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
#define switch_zmalloc(ptr, len)
switch_size_t switch_buffer_read_loop(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen)
Read data endlessly from a switch_buffer_t.
static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
switch_speech_interface_t * speech_interface
switch_input_callback_function_t input_callback
void switch_buffer_zero(_In_ switch_buffer_t *buffer)
Remove all data from the buffer.
An abstraction of a data frame.
Definition: switch_frame.h:54
uintptr_t switch_size_t
#define arg_recursion_check_start(_args)
#define switch_set_flag_locked(obj, flag)
Set a flag on an arbitrary object while locked.
Definition: switch_utils.h:707
void switch_swap_linear(int16_t *buf, int len)
Perform a byteswap on a buffer of 16 bit samples.
const char * cJSON_GetObjectCstr(const cJSON *object, const char *string)
Definition: switch_json.c:22
switch_byte_t switch_byte_t uint32_t buflen
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1693
switch_speech_handle_t sh
#define SWITCH_STANDARD_STREAM(s)
#define switch_core_service_session(_s)
Definition: switch_core.h:1216
int switch_regex_perform(const char *field, const char *expression, switch_regex_t **new_re, int *ovector, uint32_t olen)
Definition: switch_regex.c:55
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
switch_say_gender_t gender
switch_status_t switch_ivr_detect_speech(switch_core_session_t *session, const char *mod_name, const char *grammar, const char *name, const char *dest, switch_asr_handle_t *ah)
Engage background Speech detection on a session.
switch_status_t switch_core_session_wait_for_video_input_params(switch_core_session_t *session, uint32_t timeout_ms)
switch_status_t switch_core_timer_destroy(switch_timer_t *timer)
Destroy an allocated timer.
switch_status_t switch_ivr_get_file_handle(switch_core_session_t *session, switch_file_handle_t **fh)
switch_buffer_t * audio_buffer
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:82
switch_read_frame_callback_function_t read_frame_callback
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)
void switch_core_speech_flush_tts(switch_speech_handle_t *sh)
Flush TTS audio on a given handle.
static void merge_recording_variables(switch_event_t *vars, switch_event_t *event)
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:993
#define SWITCH_READ_TERMINATOR_USED_VARIABLE
Definition: switch_types.h:130
switch_status_t switch_core_timer_next(switch_timer_t *timer)
Wait for one cycle on an existing timer.
switch_status_t switch_core_media_get_vid_params(switch_core_session_t *session, switch_vid_params_t *vid_params)
switch_input_args_t * original_args
char * switch_separate_paren_args(char *str)
#define switch_channel_expand_variables(_channel, _in)
#define switch_clear_flag_locked(obj, flag)
Clear a flag on an arbitrary object.
Definition: switch_utils.h:717
#define FILE_BUFSIZE
switch_status_t
Common return values.
switch_status_t switch_ivr_play_and_collect_input(switch_core_session_t *session, const char *prompt, const char *recognizer_mod_name, const char *recognizer_grammar, int min_digits, int max_digits, const char *terminators, uint32_t digit_timeout, cJSON **recognition_result, char **digits_collected, char *terminator_collected, switch_input_args_t *args)
Play prompt and collect input.
switch_status_t switch_core_file_write(_In_ switch_file_handle_t *fh, void *data, switch_size_t *len)
Write media to a file handle.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
switch_status_t switch_ivr_detect_audio(switch_core_session_t *session, uint32_t thresh, uint32_t audio_hits, uint32_t timeout_ms, const char *file)
const cJSON *const target
switch_status_t switch_ivr_wait_for_silence(switch_core_session_t *session, uint32_t thresh, uint32_t silence_hits, uint32_t listen_hits, uint32_t timeout_ms, const char *file)
switch_status_t switch_core_session_dequeue_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event, switch_bool_t force)
DE-Queue an event on a given session.
switch_say_interface_t * switch_loadable_module_get_say_interface(const char *name)
Retrieve the say interface by it&#39;s registered name.
struct switch_event_header * next
Definition: switch_event.h:76
switch_buffer_t * sp_audio_buffer
void switch_change_sln_volume_granular(int16_t *data, uint32_t samples, int32_t vol)
Change the volume of a signed linear audio frame with more granularity.
switch_size_t switch_channel_has_dtmf(_In_ switch_channel_t *channel)
Test for presence of DTMF on a given channel.
#define switch_core_session_locate(uuid_str)
Locate a session based on it&#39;s uuid.
Definition: switch_core.h:932
#define FILE_BLOCKSIZE
static int write_buf(int fd, const char *buf)
Main Library Header.
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:384
switch_status_t switch_core_speech_open(_In_ switch_speech_handle_t *sh, const char *module_name, const char *voice_name, _In_ unsigned int rate, _In_ unsigned int interval, _In_ unsigned int channels, switch_speech_flag_t *flags, _In_opt_ switch_memory_pool_t *pool)
Open a speech handle.
static switch_bool_t switch_is_file_path(const char *file)
#define SWITCH_INT64_T_FMT
#define SWITCH_DECLARE(type)
uint32_t samples
Definition: switch_frame.h:72
#define switch_event_get_header(_e, _h)
Definition: switch_event.h:172
#define switch_channel_set_flag(_c, _f)
switch_xml_t switch_xml_child(_In_ switch_xml_t xml, _In_z_ const char *name)
returns the first child tag (one level deeper) with the given name or NULL \ if not found ...
An abstraction to store a tone generation session.
uint32_t channels
Definition: switch_frame.h:76
switch_bool_t switch_core_file_has_video(switch_file_handle_t *fh, switch_bool_t CHECK_OPEN)
switch_status_t switch_core_media_unlock_video_file(switch_core_session_t *session, switch_rw_t rw)
switch_status_t switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p)
switch_status_t switch_ivr_record_file(switch_core_session_t *session, switch_file_handle_t *fh, const char *file, switch_input_args_t *args, uint32_t limit)
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:322
switch_say_method_t switch_ivr_get_say_method_by_name(const char *name)
switch_status_t switch_ivr_release_file_handle(switch_core_session_t *session, switch_file_handle_t **fh)
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session&#39;s pool.
Definition: switch_core.h:696
#define FILE_STARTSAMPLES
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
switch_status_t switch_ivr_speak_text_handle(switch_core_session_t *session, switch_speech_handle_t *sh, switch_codec_t *codec, switch_timer_t *timer, const char *text, switch_input_args_t *args)
void switch_channel_clear_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
static switch_bool_t switch_core_codec_ready(switch_codec_t *codec)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
A table of settings and callbacks that define a paticular implementation of a codec.
#define switch_is_valid_rate(_tmp)
Definition: switch_utils.h:378
switch_status_t switch_core_media_lock_video_file(switch_core_session_t *session, switch_rw_t rw)
#define switch_ivr_phrase_macro(session, macro_name, data, lang, args)
Definition: switch_ivr.h:936
static void deliver_asr_event(switch_core_session_t *session, switch_event_t *event, switch_input_args_t *args)
int count
Definition: switch_cJSON.h:204
struct fspr_pool_t switch_memory_pool_t
const char *const name
Definition: switch_cJSON.h:250
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session&#39;s pool.
Definition: switch_core.h:719
void switch_event_destroy(switch_event_t **event)
Destroy an event.
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_assert(expr)
#define switch_channel_set_variable(_channel, _var, _val)
switch_status_t switch_ivr_record_file_event(switch_core_session_t *session, switch_file_handle_t *fh, const char *file, switch_input_args_t *args, uint32_t limit, switch_event_t *vars)
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
switch_size_t switch_buffer_inuse(_In_ switch_buffer_t *buffer)
Get the in use amount of a switch_buffer_t.
switch_status_t switch_channel_api_on(switch_channel_t *channel, const char *variable_prefix)
void switch_buffer_destroy(switch_buffer_t **buffer)
Destroy the buffer.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)
#define SWITCH_READ_ACCEPTABLE(status)
memset(buf, 0, buflen)
switch_status_t switch_ivr_soft_hold(switch_core_session_t *session, const char *unhold_key, const char *moh_a, const char *moh_b)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
switch_status_t switch_ivr_detect_speech_start_input_timers(switch_core_session_t *session)
Start input timers on a background speech detection handle.
switch_status_t switch_regex_match(const char *target, const char *expression)
Function to evaluate an expression against a string.
Definition: switch_regex.c:300
#define SWITCH_DEFAULT_FILE_BUFFER_LEN
Definition: switch_types.h:236
switch_event_header_t * headers
Definition: switch_event.h:90
switch_ivr_dmachine_t * dmachine
void switch_ivr_clear_speech_cache(switch_core_session_t *session)
switch_status_t switch_core_timer_sync(switch_timer_t *timer)
switch_status_t switch_ivr_parse_all_messages(switch_core_session_t *session)
Definition: switch_ivr.c:847
static int recording_var_true(switch_channel_t *channel, switch_event_t *vars, switch_file_handle_t *fh, const char *name)