RTS API Documentation  1.10.11
Functions | Variables
switch_core_io.c File Reference
#include <switch.h>
#include "private/switch_core_pvt.h"
+ Include dependency graph for switch_core_io.c:

Go to the source code of this file.

Functions

void switch_core_gen_encoded_silence (unsigned char *data, const switch_codec_implementation_t *read_impl, switch_size_t len)
 
switch_status_t switch_core_session_read_frame (switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
 
switch_status_t switch_core_session_perform_kill_channel (switch_core_session_t *session, const char *file, const char *func, int line, switch_signal_t sig)
 
switch_status_t switch_core_session_recv_dtmf (switch_core_session_t *session, const switch_dtmf_t *dtmf)
 
switch_status_t switch_core_session_send_dtmf (switch_core_session_t *session, const switch_dtmf_t *dtmf)
 
switch_status_t switch_core_session_send_dtmf_string (switch_core_session_t *session, const char *dtmf_string)
 Send DTMF to a session. More...
 

Variables

static char * SIG_NAMES []
 

Function Documentation

◆ switch_core_gen_encoded_silence()

void switch_core_gen_encoded_silence ( unsigned char *  data,
const switch_codec_implementation_t read_impl,
switch_size_t  len 
)

Definition at line 39 of file switch_core_io.c.

References switch_codec_implementation::ianacode, switch_codec_implementation::iananame, memset(), and switch_stristr().

Referenced by record_callback(), and switch_core_session_read_frame().

40 {
41  unsigned char g729_filler[] = {
42  114, 170, 250, 103, 54, 211, 203, 194, 94, 64,
43  229, 127, 79, 96, 207, 82, 216, 110, 245, 81,
44  114, 170, 250, 103, 54, 211, 203, 194, 94, 64,
45  229, 127, 79, 96, 207, 82, 216, 110, 245, 81,
46  114, 170, 250, 103, 54, 211, 203, 194, 94, 64,
47  229, 127, 79, 96, 207, 82, 216, 110, 245, 81,
48  114, 170, 250, 103, 54, 211, 203, 194, 94, 64,
49  229, 127, 79, 96, 207, 82, 216, 110, 245, 81,
50  114, 170, 250, 103, 54, 211, 203, 194, 94, 64,
51  229, 127, 79, 96, 207, 82, 216, 110, 245, 81,
52  114, 170, 250, 103, 54, 211, 203, 194, 94, 64,
53  229, 127, 79, 96, 207, 82, 216, 110, 245, 81,
54  114, 170, 250, 103, 54, 211, 203, 194, 94, 64,
55  229, 127, 79, 96, 207, 82, 216, 110, 245, 81
56  };
57 
58 
59  if (read_impl->ianacode == 18 || switch_stristr("g729", read_impl->iananame)) {
60  memcpy(data, g729_filler, len);
61  } else {
62  memset(data, 255, len);
63  }
64 
65 }
const char * switch_stristr(const char *instr, const char *str)
memset(buf, 0, buflen)

◆ switch_core_session_perform_kill_channel()

switch_status_t switch_core_session_perform_kill_channel ( switch_core_session_t session,
const char *  file,
const char *  func,
int  line,
switch_signal_t  sig 
)

Definition at line 956 of file switch_core_io.c.

References switch_core_session::channel, switch_core_session::endpoint_interface, switch_core_session::event_hooks, switch_endpoint_interface::io_routines, switch_io_event_hook_kill_channel::kill_channel, switch_io_routines::kill_channel, switch_io_event_hook_kill_channel::next, SIG_NAMES, switch_channel_get_name(), SWITCH_CHANNEL_ID_LOG, switch_core_session_get_uuid(), SWITCH_LOG_DEBUG10, switch_log_printf(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

958 {
961 
962  switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_core_session_get_uuid(session), SWITCH_LOG_DEBUG10, "Send signal %s [%s]\n",
963  switch_channel_get_name(session->channel), SIG_NAMES[sig]);
964 
966  if ((status = session->endpoint_interface->io_routines->kill_channel(session, sig)) == SWITCH_STATUS_SUCCESS) {
967  for (ptr = session->event_hooks.kill_channel; ptr; ptr = ptr->next) {
968  if ((status = ptr->kill_channel(session, sig)) != SWITCH_STATUS_SUCCESS) {
969  break;
970  }
971  }
972  }
973  }
974  return status;
975 }
switch_kill_channel_hook_t kill_channel
switch_io_routines_t * io_routines
switch_io_event_hooks_t event_hooks
switch_channel_t * channel
static char * SIG_NAMES[]
struct switch_io_event_hook_kill_channel * next
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
switch_status_t
Common return values.
Node in which to store custom kill channel callback hooks.
switch_io_kill_channel_t kill_channel
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.
switch_endpoint_interface_t * endpoint_interface
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.

◆ switch_core_session_read_frame()

switch_status_t switch_core_session_read_frame ( switch_core_session_t session,
switch_frame_t **  frame,
switch_io_flag_t  flags,
int  stream_id 
)

Definition at line 67 of file switch_core_io.c.

References switch_codec_implementation::actual_samples_per_second, switch_frame::buflen, switch_core_session::bug_codec, switch_core_session::bug_rwlock, switch_core_session::bugs, switch_media_bug::callback, CCS_ACTIVE, CCS_UNHELD, CF_ANSWERED, CF_AUDIO_PAUSE_READ, CF_BRIDGED, CF_CNG_PLC, CF_HOLD, CF_JITTERBUFFER_PLC, CF_PAUSE_BUGS, CF_PROXY_MODE, switch_core_session::channel, switch_audio_resampler_t::channels, switch_frame::channels, switch_frame::codec, switch_codec::codec_interface, switch_core_session::codec_read_mutex, CS_HIBERNATE, switch_codec::cur_frame, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_core_session::decoder_errors, switch_core_session::dmachine, switch_runtime::dummy_cng_frame, switch_core_session::enc_read_frame, switch_core_session::endpoint_interface, switch_core_session::event_hooks, switch_frame::flags, switch_codec_implementation::ianacode, switch_codec_implementation::iananame, if(), switch_codec_implementation::impl_id, switch_codec::implementation, switch_codec_interface::interface_name, switch_endpoint_interface::io_routines, switch_frame::m, memset(), switch_core_session_message::message_id, switch_codec_implementation::microseconds_per_packet, switch_codec::mutex, switch_media_bug::native_read_frame, switch_io_event_hook_read_frame::next, switch_media_bug::next, switch_codec_implementation::number_of_channels, switch_core_session_message::numeric_arg, switch_frame::payload, switch_media_bug::ping_frame, switch_core_session::plc, switch_frame::rate, switch_core_session::raw_read_buffer, switch_media_bug::raw_read_buffer, switch_core_session::raw_read_frame, switch_core_session::read_codec, switch_media_bug::read_demux_frame, switch_io_event_hook_read_frame::read_frame, switch_io_routines::read_frame, switch_core_session::read_frame_count, switch_core_session::read_impl, switch_media_bug::read_mutex, switch_media_bug::read_replace_frame_in, switch_media_bug::read_replace_frame_out, switch_core_session::read_resampler, switch_media_bug::ready, switch_core_session::resample_mutex, runtime, switch_frame::samples, switch_codec_implementation::samples_per_packet, switch_codec_implementation::samples_per_second, switch_frame::seq, SFF_CNG, SFF_NOT_AUDIO, SFF_PLC, SFF_PROXY_PACKET, SMBF_ANSWER_REQ, SMBF_BRIDGE_REQ, SMBF_NO_PAUSE, SMBF_PAUSE, SMBF_PRUNE, SMBF_READ_PING, SMBF_READ_REPLACE, SMBF_READ_STREAM, SMBF_TAP_NATIVE_READ, SSF_MEDIA_BUG_TAP_ONLY, SSF_READ_CODEC_RESET, SSF_READ_TRANSCODE, SSF_WARN_TRANSCODE, SSF_WRITE_CODEC_RESET, switch_frame::ssrc, switch_media_bug::stop_time, SWITCH_ABC_TYPE_READ, SWITCH_ABC_TYPE_READ_PING, SWITCH_ABC_TYPE_READ_REPLACE, SWITCH_ABC_TYPE_TAP_NATIVE_READ, switch_assert, SWITCH_BUFFER_BLOCK_FRAMES, switch_buffer_create_dynamic(), switch_buffer_inuse(), switch_buffer_read(), SWITCH_BUFFER_START_FRAMES, switch_buffer_write(), SWITCH_CAUSE_INCOMPATIBLE_DESTINATION, switch_channel_down, switch_channel_dtmf_lock(), switch_channel_dtmf_unlock(), switch_channel_event_set_data(), switch_channel_get_callstate(), switch_channel_get_name(), switch_channel_get_partner_uuid(), switch_channel_get_state(), switch_channel_hangup, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_callstate, switch_channel_test_flag(), switch_clear_flag, SWITCH_CODEC_FLAG_HAS_PLC, switch_cond_next(), switch_core_codec_copy(), switch_core_codec_decode(), switch_core_codec_encode(), switch_core_codec_ready(), switch_core_codec_reset(), switch_core_gen_encoded_silence(), switch_core_media_bug_prune(), switch_core_media_bug_test_flag(), switch_core_session_get_channel(), switch_core_session_get_name, switch_core_session_get_partner, switch_core_session_locate, switch_core_session_receive_message, switch_core_session_rwunlock(), switch_epoch_time_now(), switch_event_create, switch_event_fire, SWITCH_EVENT_SESSION_HEARTBEAT, SWITCH_FALSE, switch_ivr_dmachine_ping(), SWITCH_LOG_CRIT, SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, SWITCH_LOG_NOTICE, switch_log_printf(), SWITCH_MESSAGE_HEARTBEAT_EVENT, SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY, SWITCH_MESSAGE_RESAMPLE_EVENT, switch_mutex_lock(), switch_mutex_trylock(), switch_mutex_unlock(), switch_mux_channels(), switch_os_yield(), switch_plc_fillin(), switch_plc_init(), switch_plc_rx(), SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, switch_resample_create, switch_resample_destroy(), switch_resample_process(), SWITCH_RESAMPLE_QUALITY, switch_set_flag, SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_GENERR, SWITCH_STATUS_INUSE, SWITCH_STATUS_MEMERR, SWITCH_STATUS_NOOP, SWITCH_STATUS_NOT_INITALIZED, SWITCH_STATUS_RESAMPLE, SWITCH_STATUS_SUCCESS, switch_test_flag, switch_thread_rwlock_rdlock(), switch_thread_rwlock_unlock(), switch_thread_rwlock_wrlock(), SWITCH_TRUE, switch_unmerge_sln(), switch_yield, switch_frame::timestamp, switch_audio_resampler_t::to, switch_audio_resampler_t::to_len, switch_audio_resampler_t::to_rate, switch_core_session::track_duration, switch_core_session::track_id, TRUE, and switch_media_bug::user_data.

69 {
72  int need_codec, perfect, do_bugs = 0, do_resample = 0, is_cng = 0, tap_only = 0;
74  unsigned int flag = 0;
75  int i;
76 
77  switch_assert(session != NULL);
78 
79  tap_only = switch_test_flag(session, SSF_MEDIA_BUG_TAP_ONLY);
80 
82 
85  } else {
87  *frame = &runtime.dummy_cng_frame;
88  return SWITCH_STATUS_SUCCESS;
89  }
90 
91  if (!(session->read_codec && session->read_codec->implementation && switch_core_codec_ready(session->read_codec))) {
93  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s reading on a session with no media!\n",
96  *frame = &runtime.dummy_cng_frame;
97  return SWITCH_STATUS_SUCCESS;
98  }
99 
101  switch_yield(20000);
102  *frame = &runtime.dummy_cng_frame;
103  // switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Media Paused!!!!\n");
104  return SWITCH_STATUS_SUCCESS;
105  }
106 
107  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel));
109  return SWITCH_STATUS_FALSE;
110  }
111 
113 
114  if (!switch_core_codec_ready(session->read_codec)) {
116  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel));
118  *frame = &runtime.dummy_cng_frame;
119  return SWITCH_STATUS_FALSE;
120  }
121 
123 
124  top:
125 
126  for(i = 0; i < 2; i++) {
127  if (session->dmachine[i]) {
129  switch_ivr_dmachine_ping(session->dmachine[i], NULL);
131  }
132  }
133 
134  if (switch_channel_down(session->channel) || !switch_core_codec_ready(session->read_codec)) {
135  *frame = NULL;
136  status = SWITCH_STATUS_FALSE;
137  goto even_more_done;
138  }
139 
140 
141  status = SWITCH_STATUS_FALSE;
142  need_codec = perfect = 0;
143 
144  *frame = NULL;
145 
146  if (session->read_codec && !session->track_id && session->track_duration) {
147  if (session->read_frame_count == 0) {
148  switch_event_t *event;
149  switch_core_session_message_t msg = { 0 };
150 
151  session->read_frame_count = (session->read_impl.samples_per_second / session->read_impl.samples_per_packet) * session->track_duration;
152 
154  msg.numeric_arg = session->track_duration;
156 
158  switch_channel_event_set_data(session->channel, event);
159  switch_event_fire(&event);
160  } else {
161  session->read_frame_count--;
162  }
163  }
164 
165 
166  if (switch_channel_test_flag(session->channel, CF_HOLD)) {
168  status = SWITCH_STATUS_BREAK;
169  goto even_more_done;
170  }
171 
172  if (session->endpoint_interface->io_routines->read_frame) {
175  if ((status = session->endpoint_interface->io_routines->read_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
176  for (ptr = session->event_hooks.read_frame; ptr; ptr = ptr->next) {
177  if ((status = ptr->read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
178  break;
179  }
180  }
181  }
182 
183  if (status == SWITCH_STATUS_INUSE) {
184  *frame = &runtime.dummy_cng_frame;
185  switch_yield(20000);
186  return SWITCH_STATUS_SUCCESS;
187  }
188 
189  if (!SWITCH_READ_ACCEPTABLE(status) || !session->read_codec || !switch_core_codec_ready(session->read_codec)) {
190  *frame = NULL;
191  return SWITCH_STATUS_FALSE;
192  }
193 
195 
196  if (!switch_core_codec_ready(session->read_codec)) {
198  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel));
200  *frame = &runtime.dummy_cng_frame;
201  return SWITCH_STATUS_FALSE;
202  }
203 
205  if (!switch_core_codec_ready(session->read_codec)) {
206  *frame = NULL;
207  status = SWITCH_STATUS_FALSE;
208  goto even_more_done;
209  }
210  }
211 
212  if (status != SWITCH_STATUS_SUCCESS) {
213  goto done;
214  }
215 
216  if (!(*frame)) {
217  goto done;
218  }
219 
220  switch_assert(*frame != NULL);
221 
222  if (switch_test_flag(*frame, SFF_PROXY_PACKET)) {
223  /* Fast PASS! */
224  status = SWITCH_STATUS_SUCCESS;
225  goto done;
226  }
227 
228  switch_assert((*frame)->codec != NULL);
229 
230  if (!switch_core_codec_ready(session->read_codec) || !switch_core_codec_ready((*frame)->codec)) {
231  status = SWITCH_STATUS_FALSE;
232  goto done;
233  }
234 
235  if (session->bugs && !((*frame)->flags & SFF_CNG) && !((*frame)->flags & SFF_NOT_AUDIO)) {
236  switch_media_bug_t *bp;
238  int prune = 0;
239 
241 
242  for (bp = session->bugs; bp; bp = bp->next) {
243  ok = SWITCH_TRUE;
244 
246  continue;
247  }
248 
250  continue;
251  }
252  if (switch_test_flag(bp, SMBF_PRUNE)) {
253  prune++;
254  continue;
255  }
256 
257  if (bp->ready) {
259  if ((*frame)->codec && (*frame)->codec->implementation &&
260  (*frame)->codec->implementation->encoded_bytes_per_packet &&
261  (*frame)->datalen != (*frame)->codec->implementation->encoded_bytes_per_packet) {
262  switch_set_flag((*frame), SFF_CNG);
263  break;
264  }
265  if (bp->callback) {
266  bp->native_read_frame = *frame;
268  bp->native_read_frame = NULL;
269  }
270  }
271  }
272 
273  if ((bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) || ok == SWITCH_FALSE) {
275  prune++;
276  }
277  }
279 
280  if (prune) {
282  }
283  }
284 
285  codec_impl = *(*frame)->codec->implementation;
286 
287  if (session->read_codec->implementation->impl_id != codec_impl.impl_id) {
288  need_codec = TRUE;
289  tap_only = 0;
290  }
291 
293  do_resample = 1;
294  }
295 
296  if (tap_only) {
297  switch_media_bug_t *bp;
299  int prune = 0;
300 
301  if (session->bugs && switch_test_flag((*frame), SFF_CNG)) {
303  for (bp = session->bugs; bp; bp = bp->next) {
304  ok = SWITCH_TRUE;
305 
307  continue;
308  }
309 
311  continue;
312  }
313  if (switch_test_flag(bp, SMBF_PRUNE)) {
314  prune++;
315  continue;
316  }
317 
318  if (bp->ready && (*frame)->codec && (*frame)->codec->implementation && (*frame)->codec->implementation->encoded_bytes_per_packet) {
320  if (bp->callback) {
321  switch_frame_t tmp_frame = {0};
322  unsigned char data[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0};
323 
324 
325  tmp_frame.codec = (*frame)->codec;
326  tmp_frame.datalen = (*frame)->codec->implementation->encoded_bytes_per_packet;
327  tmp_frame.samples = (*frame)->codec->implementation->samples_per_packet;
328  tmp_frame.channels = (*frame)->codec->implementation->number_of_channels;
329  tmp_frame.data = data;
330 
331  switch_core_gen_encoded_silence(data, (*frame)->codec->implementation, tmp_frame.datalen);
332 
333  bp->native_read_frame = &tmp_frame;
335  bp->native_read_frame = NULL;
336  }
337  }
338  }
339 
340  if ((bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) || ok == SWITCH_FALSE) {
342  prune++;
343  }
344  }
346 
347  if (prune) {
349  }
350 
351 
352  }
353 
354 
355  goto done;
356  } else if (session->bugs && !need_codec) {
357  do_bugs = 1;
358  need_codec = 1;
359  }
360 
361  if (switch_test_flag(*frame, SFF_CNG)) {
362  if (!session->bugs && !session->plc) {
363  /* Check if other session has bugs */
364  unsigned int other_session_bugs = 0;
365  switch_core_session_t *other_session = NULL;
367  switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
368  if (other_session->bugs && !switch_test_flag(other_session, SSF_MEDIA_BUG_TAP_ONLY)) {
369  other_session_bugs = 1;
370  }
371  switch_core_session_rwunlock(other_session);
372  }
373 
374  /* Don't process CNG frame */
375  if (!other_session_bugs) {
376  status = SWITCH_STATUS_SUCCESS;
377  goto done;
378  }
379  }
380  is_cng = 1;
381  need_codec = 1;
382  } else if (switch_test_flag(*frame, SFF_NOT_AUDIO)) {
383  do_resample = 0;
384  do_bugs = 0;
385  need_codec = 0;
386  }
387 
388  if (switch_test_flag(session, SSF_READ_TRANSCODE) && !need_codec && switch_core_codec_ready(session->read_codec)) {
389  switch_core_session_t *other_session;
392 
393  if (uuid && (other_session = switch_core_session_locate(uuid))) {
394  switch_set_flag(other_session, SSF_READ_CODEC_RESET);
395  switch_set_flag(other_session, SSF_READ_CODEC_RESET);
396  switch_set_flag(other_session, SSF_WRITE_CODEC_RESET);
397  switch_core_session_rwunlock(other_session);
398  }
399  }
400 
401  if (switch_test_flag(session, SSF_READ_CODEC_RESET)) {
404  }
405 
406 
407  if (status == SWITCH_STATUS_SUCCESS && need_codec) {
408  switch_frame_t *enc_frame, *read_frame = *frame;
409 
411 
412  if (!switch_test_flag(session, SSF_WARN_TRANSCODE)) {
413  switch_core_session_message_t msg = { 0 };
414 
418  }
419 
420  if (read_frame->codec || (is_cng && session->plc)) {
421  session->raw_read_frame.datalen = session->raw_read_frame.buflen;
422 
423  if (is_cng) {
424  if (session->plc) {
426  is_cng = 0;
427  flag &= ~SFF_CNG;
428  } else {
430  }
431 
432  session->raw_read_frame.timestamp = 0;
434  session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t) / session->read_impl.number_of_channels;
436  read_frame = &session->raw_read_frame;
437  status = SWITCH_STATUS_SUCCESS;
438  } else {
439  switch_codec_t *use_codec = read_frame->codec;
440  if (do_bugs) {
442  if (!session->bugs) {
444  goto done;
445  }
446 
447  if (!switch_core_codec_ready(&session->bug_codec) && switch_core_codec_ready(read_frame->codec)) {
448  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setting BUG Codec %s:%d\n",
449  read_frame->codec->implementation->iananame, read_frame->codec->implementation->ianacode);
450  switch_core_codec_copy(read_frame->codec, &session->bug_codec, NULL, NULL);
451  if (!switch_core_codec_ready(&session->bug_codec)) {
452  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s Error setting BUG codec %s!\n",
454  }
455  }
456 
457  if (switch_core_codec_ready(&session->bug_codec)) {
458  use_codec = &session->bug_codec;
459  }
461 
463  if (!session->bugs) {
464  do_bugs = 0;
465  }
467  if (!do_bugs) goto done;
468  }
469 
470  if (!switch_test_flag(read_frame->codec, SWITCH_CODEC_FLAG_HAS_PLC) &&
472  switch_channel_test_flag(session->channel, CF_CNG_PLC)) && !session->plc) {
473  session->plc = switch_plc_init(NULL);
474  }
475 
476  if (!switch_test_flag(read_frame->codec, SWITCH_CODEC_FLAG_HAS_PLC) && session->plc && switch_test_flag(read_frame, SFF_PLC)) {
478  session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t) / session->read_impl.number_of_channels;
480  memset(session->raw_read_frame.data, 255, session->raw_read_frame.datalen);
481  status = SWITCH_STATUS_SUCCESS;
482  } else {
483  switch_codec_t *codec = use_codec;
484 
486 
487  if (!switch_core_codec_ready(codec)) {
488  codec = read_frame->codec;
489  }
490 
491  if (!switch_core_codec_ready(codec)) {
493  goto done;
494  }
495 
496  codec->cur_frame = read_frame;
497  session->read_codec->cur_frame = read_frame;
498  status = switch_core_codec_decode(codec,
499  session->read_codec,
500  read_frame->data,
501  read_frame->datalen,
503  session->raw_read_frame.data, &session->raw_read_frame.datalen, &session->raw_read_frame.rate,
504  &read_frame->flags);
505 
506  if (status == SWITCH_STATUS_NOT_INITALIZED) {
508  goto done;
509  }
510 
511  session->raw_read_frame.samples = session->raw_read_frame.datalen / 2;
513  codec->cur_frame = NULL;
514  session->read_codec->cur_frame = NULL;
516 
517  }
518 
519  if (status == SWITCH_STATUS_SUCCESS && session->read_impl.number_of_channels == 1) {
520  if (session->plc) {
521  if (switch_test_flag(read_frame, SFF_PLC)) {
522  switch_plc_fillin(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2);
523  switch_clear_flag(read_frame, SFF_PLC);
524  } else {
525  switch_plc_rx(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2);
526  }
527  }
528  }
529 
530 
531  }
532 
533  if (do_resample && ((status == SWITCH_STATUS_SUCCESS) || is_cng)) {
534  status = SWITCH_STATUS_RESAMPLE;
535  }
536 
537  /* mux or demux to match */
538  if (session->raw_read_frame.channels != session->read_impl.number_of_channels) {
539  uint32_t rlen = session->raw_read_frame.datalen / 2 / session->raw_read_frame.channels;
540  switch_mux_channels((int16_t *) session->raw_read_frame.data, rlen, session->raw_read_frame.channels, session->read_impl.number_of_channels);
541  session->raw_read_frame.datalen = rlen * 2 * session->read_impl.number_of_channels;
542  session->raw_read_frame.samples = session->raw_read_frame.datalen / 2;
544  }
545 
546 
547  switch (status) {
549  if (!session->read_resampler) {
551 
552  status = switch_resample_create(&session->read_resampler,
556  session->read_impl.number_of_channels);
557 
559 
560  if (status != SWITCH_STATUS_SUCCESS) {
561  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to allocate resampler\n");
562  status = SWITCH_STATUS_FALSE;
563  goto done;
564  } else {
565  switch_core_session_message_t msg = { 0 };
566  msg.numeric_arg = 1;
569 
570  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Activating read resampler\n");
571  }
572  }
574  session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t) / session->read_impl.number_of_channels;
576  session->raw_read_frame.rate = read_frame->rate;
578  session->raw_read_frame.timestamp = 0;
579  } else {
580  session->raw_read_frame.timestamp = read_frame->timestamp;
581  }
582  session->raw_read_frame.ssrc = read_frame->ssrc;
583  session->raw_read_frame.seq = read_frame->seq;
584  session->raw_read_frame.m = read_frame->m;
585  session->raw_read_frame.payload = read_frame->payload;
586  session->raw_read_frame.flags = 0;
587  if (switch_test_flag(read_frame, SFF_PLC)) {
588  session->raw_read_frame.flags |= SFF_PLC;
589  }
590  read_frame = &session->raw_read_frame;
591  break;
592  case SWITCH_STATUS_NOOP:
593  if (session->read_resampler) {
596  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating read resampler\n");
598 
599  {
600  switch_core_session_message_t msg = { 0 };
601  msg.numeric_arg = 0;
604  }
605 
606  }
607 
608  status = SWITCH_STATUS_SUCCESS;
609  break;
610  case SWITCH_STATUS_BREAK:
613  session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t) / session->read_impl.number_of_channels;
615  session->raw_read_frame.timestamp = read_frame->timestamp;
616  session->raw_read_frame.rate = read_frame->rate;
617  session->raw_read_frame.ssrc = read_frame->ssrc;
618  session->raw_read_frame.seq = read_frame->seq;
619  session->raw_read_frame.m = read_frame->m;
620  session->raw_read_frame.payload = read_frame->payload;
621  session->raw_read_frame.flags = 0;
622  if (switch_test_flag(read_frame, SFF_PLC)) {
623  session->raw_read_frame.flags |= SFF_PLC;
624  }
625 
626  read_frame = &session->raw_read_frame;
627  status = SWITCH_STATUS_SUCCESS;
628  break;
630  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
631  goto done;
632  default:
633  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error! [%d]\n",
634  session->read_codec->codec_interface->interface_name, status);
635 
636  if (++session->decoder_errors < 10) {
637  status = SWITCH_STATUS_SUCCESS;
638  } else {
639  goto done;
640  }
641  }
642 
643  session->decoder_errors = 0;
644  }
645 
646  if (session->bugs) {
647  switch_media_bug_t *bp;
649  int prune = 0;
651 
652  for (bp = session->bugs; bp; bp = bp->next) {
653  ok = SWITCH_TRUE;
654 
656  continue;
657  }
658 
660  continue;
661  }
662 
664  continue;
665  }
666 
667  if (switch_test_flag(bp, SMBF_PRUNE)) {
668  prune++;
669  continue;
670  }
671 
673  do_bugs = 0;
674  if (bp->callback) {
675  bp->read_replace_frame_in = read_frame;
676  bp->read_replace_frame_out = read_frame;
677  bp->read_demux_frame = NULL;
678  if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_REPLACE)) == SWITCH_TRUE) {
679  read_frame = bp->read_replace_frame_out;
680  }
681  }
682  }
683 
684  if ((bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) || ok == SWITCH_FALSE) {
686  prune++;
687  }
688 
689 
690  }
692  if (prune) {
694  }
695  }
696 
697  if (session->bugs) {
698  switch_media_bug_t *bp;
700  int prune = 0;
702 
703  for (bp = session->bugs; bp; bp = bp->next) {
704  ok = SWITCH_TRUE;
705 
707  continue;
708  }
709 
711  continue;
712  }
713 
715  continue;
716  }
717 
718  if (switch_test_flag(bp, SMBF_PRUNE)) {
719  prune++;
720  continue;
721  }
722 
723  if (bp->ready && switch_test_flag(bp, SMBF_READ_STREAM)) {
725  if (bp->read_demux_frame) {
726  uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
727  int bytes = read_frame->datalen;
728  uint32_t datalen = 0;
729  uint32_t samples = bytes / 2 / bp->read_demux_frame->channels;
730 
731  memcpy(data, read_frame->data, read_frame->datalen);
732  datalen = switch_unmerge_sln((int16_t *)data, samples,
733  bp->read_demux_frame->data, samples,
735 
736  switch_buffer_write(bp->raw_read_buffer, data, datalen);
737  } else {
738  switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen);
739  }
740 
741  if (bp->callback) {
742  ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ);
743  }
745  }
746 
747  if ((bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) || ok == SWITCH_FALSE) {
749  prune++;
750  }
751  }
753  if (prune) {
755  }
756  }
757 
758  if (do_bugs) {
759  goto done;
760  }
761 
762  if (session->read_codec) {
763  if (session->read_resampler) {
764  short *data = read_frame->data;
766  switch_resample_process(session->read_resampler, data, (int) read_frame->datalen / 2 / session->read_resampler->channels);
767  memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2 * session->read_resampler->channels);
768  read_frame->samples = session->read_resampler->to_len;
769  read_frame->channels = session->read_resampler->channels;
770  read_frame->datalen = session->read_resampler->to_len * 2 * session->read_resampler->channels;
771  read_frame->rate = session->read_resampler->to_rate;
773  }
774 
775  if (read_frame->datalen == session->read_impl.decoded_bytes_per_packet) {
776  perfect = TRUE;
777  } else {
778  if (!session->raw_read_buffer) {
780  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Engaging Read Buffer at %u bytes vs %u\n",
781  (uint32_t) bytes, (uint32_t) (*frame)->datalen);
783  }
784 
785  if (read_frame->datalen && (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen))) {
786  status = SWITCH_STATUS_MEMERR;
787  goto done;
788  }
789  }
790 
791  if (perfect || switch_buffer_inuse(session->raw_read_buffer) >= session->read_impl.decoded_bytes_per_packet) {
792  if (perfect) {
793  enc_frame = read_frame;
794  session->raw_read_frame.rate = read_frame->rate;
795  } else {
796  session->raw_read_frame.datalen = (uint32_t) switch_buffer_read(session->raw_read_buffer,
797  session->raw_read_frame.data,
799 
801  enc_frame = &session->raw_read_frame;
802  }
803  session->enc_read_frame.datalen = session->enc_read_frame.buflen;
804 
805  switch_assert(session->read_codec != NULL);
806  switch_assert(enc_frame != NULL);
807  switch_assert(enc_frame->data != NULL);
808  session->read_codec->cur_frame = enc_frame;
809  enc_frame->codec->cur_frame = enc_frame;
812  status = switch_core_codec_encode(session->read_codec,
813  enc_frame->codec,
814  enc_frame->data,
815  enc_frame->datalen,
817  session->enc_read_frame.data, &session->enc_read_frame.datalen, &session->enc_read_frame.rate, &flag);
819 
820  session->read_codec->cur_frame = NULL;
821  enc_frame->codec->cur_frame = NULL;
822  switch (status) {
826  session->enc_read_frame.samples = session->read_impl.decoded_bytes_per_packet / sizeof(int16_t) / session->read_impl.number_of_channels;
828  if (perfect) {
829  if (enc_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) {
830  session->enc_read_frame.timestamp = 0;
831  } else {
832  session->enc_read_frame.timestamp = read_frame->timestamp;
833  }
834  session->enc_read_frame.rate = read_frame->rate;
835  session->enc_read_frame.ssrc = read_frame->ssrc;
836  session->enc_read_frame.seq = read_frame->seq;
837  session->enc_read_frame.m = read_frame->m;
838  session->enc_read_frame.payload = session->read_impl.ianacode;
839  }
840  *frame = &session->enc_read_frame;
841  break;
842  case SWITCH_STATUS_NOOP:
845  session->raw_read_frame.timestamp = read_frame->timestamp;
846  session->raw_read_frame.payload = enc_frame->codec->implementation->ianacode;
847  session->raw_read_frame.m = read_frame->m;
848  session->raw_read_frame.ssrc = read_frame->ssrc;
849  session->raw_read_frame.seq = read_frame->seq;
850  *frame = enc_frame;
851  status = SWITCH_STATUS_SUCCESS;
852  break;
854  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
855  *frame = NULL;
856  status = SWITCH_STATUS_GENERR;
857  break;
858  default:
859  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error!\n",
861  *frame = NULL;
862  status = SWITCH_STATUS_GENERR;
863  break;
864  }
865  } else {
866  goto top;
867  }
868  }
869  }
870 
871  done:
872  if (!(*frame)) {
873  status = SWITCH_STATUS_FALSE;
874  } else {
875  if (flag & SFF_CNG) {
876  switch_set_flag((*frame), SFF_CNG);
877  }
878  if (session->bugs) {
879  switch_media_bug_t *bp;
881  int prune = 0;
883  for (bp = session->bugs; bp; bp = bp->next) {
884  ok = SWITCH_TRUE;
885 
887  continue;
888  }
889 
891  continue;
892  }
893 
895  continue;
896  }
897 
898  if (switch_test_flag(bp, SMBF_PRUNE)) {
899  prune++;
900  continue;
901  }
902 
903  if (bp->ready && switch_test_flag(bp, SMBF_READ_PING)) {
905  bp->ping_frame = *frame;
906  if (bp->callback) {
908  || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
909  ok = SWITCH_FALSE;
910  }
911  }
912  bp->ping_frame = NULL;;
914  }
915 
916  if (ok == SWITCH_FALSE) {
918  prune++;
919  }
920  }
922  if (prune) {
924  }
925  }
926  }
927 
928  even_more_done:
929 
930  if (!*frame ||
931  (!switch_test_flag(*frame, SFF_PROXY_PACKET) &&
932  (!(*frame)->codec || !(*frame)->codec->implementation || !switch_core_codec_ready((*frame)->codec)))) {
933  *frame = &runtime.dummy_cng_frame;
934  }
935 
938 
939 
942  }
943 
944 
945  return status;
946 }
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:413
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it&#39;s state machine to end.
switch_bool_t m
Definition: switch_frame.h:83
switch_status_t switch_thread_rwlock_unlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:286
switch_frame_t dummy_cng_frame
#define SWITCH_BUFFER_START_FRAMES
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_thread_rwlock_t * bug_rwlock
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700
switch_core_session_message_types_t message_id
Definition: switch_core.h:183
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_frame_t * read_replace_frame_in
switch_status_t switch_mutex_trylock(switch_mutex_t *lock)
Definition: switch_apr.c:318
const char * switch_channel_get_partner_uuid(switch_channel_t *channel)
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_frame_t enc_read_frame
switch_read_frame_hook_t read_frame
switch_io_read_frame_t read_frame
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:590
switch_mutex_t * codec_read_mutex
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_bool_t
Definition: switch_types.h:437
uint32_t timestamp
Definition: switch_frame.h:80
switch_status_t switch_core_codec_encode(switch_codec_t *codec, switch_codec_t *other_codec, void *decoded_data, uint32_t decoded_data_len, uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag)
Encode data using a codec handle.
switch_codec_t * read_codec
Representation of an event.
Definition: switch_event.h:80
switch_frame_t * cur_frame
switch_io_routines_t * io_routines
switch_status_t switch_core_codec_decode(switch_codec_t *codec, switch_codec_t *other_codec, void *encoded_data, uint32_t encoded_data_len, uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag)
Decode data using a codec handle.
#define SWITCH_RESAMPLE_QUALITY
switch_codec_implementation_t read_impl
struct switch_io_event_hook_read_frame * next
#define switch_core_session_get_name(_s)
Definition: switch_core.h:265
uint32_t ssrc
Definition: switch_frame.h:82
switch_plc_state_t * plc
void switch_resample_destroy(switch_audio_resampler_t **resampler)
Destroy an existing resampler handle.
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.
struct switch_runtime runtime
Definition: switch_core.c:86
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_codec_t * codec
Definition: switch_frame.h:56
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:179
switch_media_bug_callback_t callback
uint32_t switch_unmerge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples, int channels)
switch_status_t switch_core_codec_reset(switch_codec_t *codec)
switch_io_event_hooks_t event_hooks
switch_mutex_t * read_mutex
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_status_t switch_thread_rwlock_rdlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:250
_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 switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
Definition: switch_utils.h:724
switch_status_t switch_thread_rwlock_wrlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:260
SWITCH_BEGIN_EXTERN_C switch_plc_state_t * switch_plc_init(switch_plc_state_t *s)
uint16_t seq
Definition: switch_frame.h:81
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:70
void switch_os_yield(void)
Definition: switch_time.c:142
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
uint32_t switch_core_media_bug_prune(switch_core_session_t *session)
switch_channel_t * channel
switch_audio_resampler_t * read_resampler
uint32_t datalen
Definition: switch_frame.h:68
switch_codec_interface_t * codec_interface
switch_frame_t * ping_frame
switch_frame_flag_t flags
Definition: switch_frame.h:85
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
int switch_plc_rx(switch_plc_state_t *s, int16_t amp[], int len)
uint32_t rate
Definition: switch_frame.h:74
void switch_core_gen_encoded_silence(unsigned char *data, const switch_codec_implementation_t *read_impl, switch_size_t len)
switch_status_t switch_core_codec_copy(switch_codec_t *codec, switch_codec_t *new_codec, const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool)
switch_media_bug_t * bugs
switch_mutex_t * resample_mutex
An abstraction of a data frame.
Definition: switch_frame.h:54
uintptr_t switch_size_t
struct switch_media_bug * next
void switch_cond_next(void)
Definition: switch_time.c:658
#define switch_core_session_get_partner(_session, _partner)
Definition: switch_core.h:1028
switch_buffer_t * raw_read_buffer
Node in which to store custom read frame channel callback hooks.
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1247
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
switch_status_t switch_channel_dtmf_lock(switch_channel_t *channel)
switch_codec_t bug_codec
switch_frame_t raw_read_frame
void switch_mux_channels(int16_t *data, switch_size_t samples, uint32_t orig_channels, uint32_t channels)
#define switch_channel_down(_channel)
#define switch_channel_set_callstate(channel, state)
switch_status_t
Common return values.
#define switch_core_session_locate(uuid_str)
Locate a session based on it&#39;s uuid.
Definition: switch_core.h:932
#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
uint32_t samples
Definition: switch_frame.h:72
uint32_t channels
Definition: switch_frame.h:76
switch_status_t switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p)
int switch_plc_fillin(switch_plc_state_t *s, int16_t amp[], int len)
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:322
switch_ivr_dmachine_t * dmachine[2]
switch_payload_t payload
Definition: switch_frame.h:78
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
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.
switch_channel_callstate_t switch_channel_get_callstate(switch_channel_t *channel)
switch_endpoint_interface_t * endpoint_interface
switch_mutex_t * mutex
uint32_t switch_core_media_bug_test_flag(_In_ switch_media_bug_t *bug, _In_ uint32_t flag)
Test for the existance of a flag on an media bug.
#define TRUE
switch_buffer_t * raw_read_buffer
#define switch_assert(expr)
switch_frame_t * read_replace_frame_out
switch_frame_t * read_demux_frame
#define SWITCH_BUFFER_BLOCK_FRAMES
switch_size_t switch_buffer_inuse(_In_ switch_buffer_t *buffer)
Get the in use amount of a switch_buffer_t.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
#define SWITCH_READ_ACCEPTABLE(status)
memset(buf, 0, buflen)
#define switch_resample_create(_n, _fr, _tr, _ts, _q, _c)
switch_frame_t * native_read_frame
uint32_t switch_resample_process(switch_audio_resampler_t *resampler, int16_t *src, uint32_t srclen)
Resample one float buffer into another using specifications of a given handle.
switch_status_t switch_channel_dtmf_unlock(switch_channel_t *channel)

◆ switch_core_session_recv_dtmf()

switch_status_t switch_core_session_recv_dtmf ( switch_core_session_t session,
const switch_dtmf_t dtmf 
)

Definition at line 977 of file switch_core_io.c.

References switch_core_session::channel, switch_dtmf_t::digit, switch_core_session::dmachine, DTMF_FLAG_SENSITIVE, DTMF_FLAG_SKIP_PROCESS, switch_dtmf_t::duration, switch_core_session::event_hooks, switch_io_event_hook_recv_dtmf::next, switch_io_event_hook_recv_dtmf::recv_dtmf, switch_assert, switch_channel_down, switch_channel_get_name(), SWITCH_CHANNEL_SESSION_LOG, switch_core_default_dtmf_duration(), switch_core_max_dtmf_duration(), switch_core_min_dtmf_duration(), SWITCH_DTMF_RECV, switch_ivr_dmachine_feed(), SWITCH_LOG_DEBUG1, switch_log_printf(), SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and switch_test_flag.

978 {
980  switch_status_t status;
981  switch_dtmf_t new_dtmf;
982  int fed = 0;
983 
984  if (switch_channel_down(session->channel)) {
985  return SWITCH_STATUS_FALSE;
986  }
987 
988  switch_assert(dtmf);
989 
991  return SWITCH_STATUS_SUCCESS;
992  }
993 
994  new_dtmf = *dtmf;
995 
996  if (new_dtmf.duration > switch_core_max_dtmf_duration(0)) {
997  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n",
998  switch_channel_get_name(session->channel), new_dtmf.digit, new_dtmf.duration);
1000  } else if (new_dtmf.duration < switch_core_min_dtmf_duration(0)) {
1001  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n",
1002  switch_channel_get_name(session->channel), new_dtmf.digit, new_dtmf.duration);
1004  } else if (!new_dtmf.duration) {
1006  }
1007 
1009  if (session->dmachine[0]) {
1010  char str[2] = { dtmf->digit, '\0' };
1011  switch_ivr_dmachine_feed(session->dmachine[0], str, NULL);
1012  fed = 1;
1013  }
1014 
1015  for (ptr = session->event_hooks.recv_dtmf; ptr; ptr = ptr->next) {
1016  if ((status = ptr->recv_dtmf(session, &new_dtmf, SWITCH_DTMF_RECV)) != SWITCH_STATUS_SUCCESS) {
1017  return status;
1018  }
1019  }
1020  }
1021 
1023 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_status_t switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match)
uint32_t duration
Definition: switch_types.h:298
uint32_t switch_core_max_dtmf_duration(uint32_t duration)
Definition: switch_core.c:1704
switch_io_event_hooks_t event_hooks
uint32_t switch_core_min_dtmf_duration(uint32_t duration)
Definition: switch_core.c:1744
switch_channel_t * channel
uint32_t switch_core_default_dtmf_duration(uint32_t duration)
Definition: switch_core.c:1721
#define switch_channel_down(_channel)
switch_status_t
Common return values.
struct switch_io_event_hook_recv_dtmf * next
switch_ivr_dmachine_t * dmachine[2]
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
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.
#define switch_assert(expr)
Node in which to store custom recv dtmf channel callback hooks.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.

◆ switch_core_session_send_dtmf()

switch_status_t switch_core_session_send_dtmf ( switch_core_session_t session,
const switch_dtmf_t dtmf 
)

Definition at line 1025 of file switch_core_io.c.

References CC_QUEUEABLE_DTMF_DELAY, CF_DROP_DTMF, switch_core_session::channel, switch_dtmf_t::digit, switch_core_session::dmachine, DTMF_FLAG_SENSITIVE, DTMF_FLAG_SKIP_PROCESS, switch_dtmf_t::duration, switch_core_session::endpoint_interface, switch_core_session::event_hooks, switch_endpoint_interface::io_routines, is_dtmf, switch_io_event_hook_send_dtmf::next, switch_io_event_hook_send_dtmf::send_dtmf, switch_io_routines::send_dtmf, SMF_ECHO_ALEG, switch_assert, switch_channel_clear_flag(), switch_channel_down, switch_channel_get_name(), switch_channel_get_variable_dup(), SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_flag, switch_channel_test_cap(), switch_channel_test_flag(), switch_core_default_dtmf_duration(), switch_core_max_dtmf_duration(), switch_core_min_dtmf_duration(), switch_core_session_get_uuid(), SWITCH_DTMF_SEND, SWITCH_FALSE, switch_ivr_broadcast(), switch_ivr_dmachine_feed(), switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_test_flag, switch_yield, and zstr.

Referenced by switch_core_session_send_dtmf_string().

1026 {
1029  switch_dtmf_t new_dtmf;
1030 
1031  if (switch_channel_down(session->channel)) {
1032  return SWITCH_STATUS_FALSE;
1033  }
1034 
1036  return SWITCH_STATUS_SUCCESS;
1037  }
1038 
1040  const char *file = switch_channel_get_variable_dup(session->channel, "drop_dtmf_masking_file", SWITCH_FALSE, -1);
1041  const char *digits;
1042 
1043  if (!zstr(file)) {
1045  }
1046 
1047  if ((digits = switch_channel_get_variable_dup(session->channel, "drop_dtmf_masking_digits", SWITCH_FALSE, -1)) && !zstr(digits)) {
1048  const char *p;
1050 
1052  for(p = digits; p && *p; p++) {
1053  if (is_dtmf(*p)) {
1054  x_dtmf.digit = *p;
1055  switch_core_session_send_dtmf(session, &x_dtmf);
1056  }
1057  }
1059  }
1060 
1061  return SWITCH_STATUS_SUCCESS;
1062  }
1063 
1064  switch_assert(dtmf);
1065 
1066  new_dtmf = *dtmf;
1067 
1068  if (new_dtmf.digit != 'w' && new_dtmf.digit != 'W') {
1069  if (new_dtmf.duration > switch_core_max_dtmf_duration(0)) {
1070  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n",
1071  switch_channel_get_name(session->channel), new_dtmf.digit, new_dtmf.duration);
1073  } else if (new_dtmf.duration < switch_core_min_dtmf_duration(0)) {
1074  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n",
1075  switch_channel_get_name(session->channel), new_dtmf.digit, new_dtmf.duration);
1077  }
1078  }
1079 
1080  if (!new_dtmf.duration) {
1082  }
1083 
1085  for (ptr = session->event_hooks.send_dtmf; ptr; ptr = ptr->next) {
1086  if ((status = ptr->send_dtmf(session, dtmf, SWITCH_DTMF_SEND)) != SWITCH_STATUS_SUCCESS) {
1087  return SWITCH_STATUS_SUCCESS;
1088  }
1089  }
1090  if (session->dmachine[1]) {
1091  char str[2] = { new_dtmf.digit, '\0' };
1092  switch_ivr_dmachine_feed(session->dmachine[1], str, NULL);
1093  return SWITCH_STATUS_SUCCESS;
1094  }
1095  }
1096 
1097 
1098  if (session->endpoint_interface->io_routines->send_dtmf) {
1099  int send = 0;
1100  status = SWITCH_STATUS_SUCCESS;
1101 
1102  if (switch_channel_test_cap(session->channel, CC_QUEUEABLE_DTMF_DELAY) && (dtmf->digit == 'w' || dtmf->digit == 'W')) {
1103  send = 1;
1104  } else {
1105  if (dtmf->digit == 'w') {
1106  switch_yield(500000);
1107  } else if (dtmf->digit == 'W') {
1108  switch_yield(1000000);
1109  } else {
1110  send = 1;
1111  }
1112  }
1113 
1114  if (send) {
1115  status = session->endpoint_interface->io_routines->send_dtmf(session, &new_dtmf);
1116  }
1117  }
1118  return status;
1119 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_status_t switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match)
switch_io_send_dtmf_t send_dtmf
struct switch_io_event_hook_send_dtmf * next
switch_status_t switch_ivr_broadcast(const char *uuid, const char *path, switch_media_flag_t flags)
Signal the session to broadcast audio.
switch_io_routines_t * io_routines
const char * switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup, int idx)
Retrieve a variable from a given channel.
uint32_t duration
Definition: switch_types.h:298
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.
#define zstr(x)
Definition: switch_utils.h:314
uint32_t switch_core_max_dtmf_duration(uint32_t duration)
Definition: switch_core.c:1704
#define is_dtmf(key)
determine if a character is a valid DTMF key
Definition: switch_utils.h:683
switch_io_event_hooks_t event_hooks
uint32_t switch_core_min_dtmf_duration(uint32_t duration)
Definition: switch_core.c:1744
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:998
switch_channel_t * channel
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
uint32_t switch_channel_test_cap(switch_channel_t *channel, switch_channel_cap_t cap)
uint32_t switch_core_default_dtmf_duration(uint32_t duration)
Definition: switch_core.c:1721
#define switch_channel_down(_channel)
switch_status_t
Common return values.
Node in which to store custom send dtmf channel callback hooks.
#define switch_channel_set_flag(_c, _f)
switch_ivr_dmachine_t * dmachine[2]
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
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.
switch_endpoint_interface_t * endpoint_interface
switch_status_t switch_core_session_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
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)
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.

Variable Documentation

◆ SIG_NAMES

char* SIG_NAMES[]
static
Initial value:
= {
"NONE",
"KILL",
"XFER",
"BREAK",
NULL
}

Definition at line 948 of file switch_core_io.c.

Referenced by switch_core_session_perform_kill_channel().