2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
26 * Anthony Minessale II <anthm@freeswitch.org>
29 * switch_cpp.cpp -- C++ wrapper
34 #include <switch_cpp.h>
37 #pragma warning(disable:4127 4003)
40 static void event_handler(switch_event_t
*event
)
42 EventConsumer
*E
= (EventConsumer
*) event
->bind_user_data
;
45 switch_event_dup(&dup
, event
);
47 if (switch_queue_trypush(E
->events
, dup
) != SWITCH_STATUS_SUCCESS
) {
48 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Cannot queue any more events.....\n");
49 switch_event_destroy(&dup
);
54 SWITCH_DECLARE_CONSTRUCTOR
EventConsumer::EventConsumer(const char *event_name
, const char *subclass_name
, int len
)
57 switch_core_new_memory_pool(&pool
);
58 switch_queue_create(&events
, len
, pool
);
62 if (!zstr(event_name
)) {
63 bind(event_name
, subclass_name
);
67 SWITCH_DECLARE(int) EventConsumer::bind(const char *event_name
, const char *subclass_name
)
69 switch_event_types_t event_id
= SWITCH_EVENT_CUSTOM
;
75 if (switch_name_event(event_name
, &event_id
) != SWITCH_STATUS_SUCCESS
) {
76 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "Can't bind to %s, event not found\n", event_name
);
80 if (zstr(subclass_name
)) {
84 if (node_index
<= SWITCH_EVENT_ALL
&&
85 switch_event_bind_removable(__FILE__
, event_id
, subclass_name
, event_handler
, this, &enodes
[node_index
]) == SWITCH_STATUS_SUCCESS
) {
86 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_DEBUG
, "bound to %s %s\n", event_name
, switch_str_nil(subclass_name
));
91 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Cannot bind to %s %s\n", event_name
, switch_str_nil(subclass_name
));
96 SWITCH_DECLARE(Event
*) EventConsumer::pop(int block
, int timeout
)
100 switch_event_t
*event
;
109 res
= switch_queue_pop_timeout(events
, &pop
, (switch_interval_time_t
) timeout
* 1000); // millisec rather than microsec
111 res
= switch_queue_pop(events
, &pop
);
114 res
= switch_queue_trypop(events
, &pop
);
119 if ((event
= (switch_event_t
*) pop
)) {
120 ret
= new Event(event
, 1);
126 SWITCH_DECLARE(void) EventConsumer::cleanup()
138 for (i
= 0; i
< node_index
; i
++) {
139 switch_event_unbind(&enodes
[i
]);
144 switch_queue_interrupt_all(events
);
146 while(switch_queue_trypop(events
, &pop
) == SWITCH_STATUS_SUCCESS
) {
147 switch_event_t
*event
= (switch_event_t
*) pop
;
148 switch_event_destroy(&event
);
152 switch_core_destroy_memory_pool(&pool
);
157 SWITCH_DECLARE_CONSTRUCTOR
EventConsumer::~EventConsumer()
162 SWITCH_DECLARE_CONSTRUCTOR
IVRMenu::IVRMenu(IVRMenu
*main
,
164 const char *greeting_sound
,
165 const char *short_greeting_sound
,
166 const char *invalid_sound
,
167 const char *exit_sound
,
168 const char *transfer_sound
,
169 const char *confirm_macro
,
170 const char *confirm_key
,
171 const char *tts_engine
,
172 const char *tts_voice
,
173 int confirm_attempts
,
181 switch_core_new_memory_pool(&pool
);
187 switch_ivr_menu_init(&menu
, main
? main
->menu
: NULL
, name
, greeting_sound
, short_greeting_sound
, invalid_sound
,
188 exit_sound
, transfer_sound
, confirm_macro
, confirm_key
, tts_engine
, tts_voice
, confirm_attempts
, inter_timeout
,
189 digit_len
, timeout
, max_failures
, max_timeouts
, pool
);
194 SWITCH_DECLARE_CONSTRUCTOR
IVRMenu::~IVRMenu()
197 switch_ivr_menu_stack_free(menu
);
199 switch_core_destroy_memory_pool(&pool
);
202 SWITCH_DECLARE(void) IVRMenu::bindAction(char *action
, const char *arg
, const char *bind
)
204 switch_ivr_action_t ivr_action
= SWITCH_IVR_ACTION_NOOP
;
208 if (switch_ivr_menu_str2action(action
, &ivr_action
) == SWITCH_STATUS_SUCCESS
) {
209 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_DEBUG
, "bind %s to %s(%s)\n", bind
, action
, arg
);
210 switch_ivr_menu_bind_action(menu
, ivr_action
, arg
, bind
);
212 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "invalid action %s\n", action
);
216 SWITCH_DECLARE(void) IVRMenu::execute(CoreSession
*session
, const char *name
)
219 switch_ivr_menu_execute(session
->session
, menu
, (char *)name
, NULL
);
222 SWITCH_DECLARE_CONSTRUCTOR
API::API(CoreSession
*s
)
225 session
= s
->session
;
231 SWITCH_DECLARE_CONSTRUCTOR
API::~API()
237 SWITCH_DECLARE(const char *) API::execute(const char *cmd
, const char *arg
)
239 switch_stream_handle_t stream
= { 0 };
242 SWITCH_STANDARD_STREAM(stream
);
245 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No application specified\n");
246 stream
.write_function(&stream
, "-ERR No application specified");
248 switch_api_execute(cmd
, arg
, session
, &stream
);
251 return (char *) stream
.data
;
255 /* we have to do this as a string because swig and languages can't find an embedded way to pass a big int */
256 SWITCH_DECLARE(char *) API::getTime(void)
258 switch_time_t now
= switch_micro_time_now() / 1000;
259 snprintf(time_buf
, sizeof(time_buf
), "%" SWITCH_TIME_T_FMT
, now
);
265 SWITCH_DECLARE(const char *) API::executeString(const char *cmd
)
268 switch_stream_handle_t stream
= { 0 };
273 SWITCH_STANDARD_STREAM(stream
);
276 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No application specified\n");
277 stream
.write_function(&stream
, "-ERR No application specified");
281 switch_assert(mycmd
);
283 if ((arg
= strchr(mycmd
, ' '))) {
287 switch_api_execute(mycmd
, arg
, session
, &stream
);
288 switch_safe_free(mycmd
);
291 return (char *) stream
.data
;
294 SWITCH_DECLARE_CONSTRUCTOR
Event::Event(const char *type
, const char *subclass_name
)
296 switch_event_types_t event_id
;
298 if (!strcasecmp(type
, "json") && !zstr(subclass_name
)) {
299 if (switch_event_create_json(&event
, subclass_name
) != SWITCH_STATUS_SUCCESS
) {
303 event_id
= event
->event_id
;
306 if (switch_name_event(type
, &event_id
) != SWITCH_STATUS_SUCCESS
) {
307 event_id
= SWITCH_EVENT_MESSAGE
;
310 if (!zstr(subclass_name
) && event_id
!= SWITCH_EVENT_CUSTOM
) {
311 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_WARNING
, "Changing event type to custom because you specified a subclass name!\n");
312 event_id
= SWITCH_EVENT_CUSTOM
;
315 if (switch_event_create_subclass(&event
, event_id
, subclass_name
) != SWITCH_STATUS_SUCCESS
) {
316 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Failed to create event!\n");
321 serialized_string
= NULL
;
325 SWITCH_DECLARE_CONSTRUCTOR
Event::Event(switch_event_t
*wrap_me
, int free_me
)
329 serialized_string
= NULL
;
332 SWITCH_DECLARE_CONSTRUCTOR
Event::~Event()
335 if (serialized_string
) {
336 free(serialized_string
);
340 switch_event_destroy(&event
);
344 SWITCH_DECLARE(int)Event::chat_execute(const char *app
, const char *data
)
346 return (int) switch_core_execute_chat_app(event
, app
, data
);
349 SWITCH_DECLARE(int)Event::chat_send(const char *dest_proto
)
351 if (zstr(dest_proto
)) {
352 dest_proto
= switch_event_get_header(event
, "dest_proto");
355 return (int) switch_core_chat_send(dest_proto
, event
);
358 SWITCH_DECLARE(const char *)Event::serialize(const char *format
)
363 switch_safe_free(serialized_string
);
369 if (format
&& !strcasecmp(format
, "xml")) {
371 if ((xml
= switch_event_xmlize(event
, SWITCH_VA_NONE
))) {
372 serialized_string
= switch_xml_toxml(xml
, SWITCH_FALSE
);
373 switch_xml_free(xml
);
374 return serialized_string
;
378 } else if (format
&& !strcasecmp(format
, "json")) {
379 switch_event_serialize_json(event
, &serialized_string
);
380 return serialized_string
;
382 if (switch_event_serialize(event
, &serialized_string
, SWITCH_TRUE
) == SWITCH_STATUS_SUCCESS
) {
383 char *new_serialized_string
= switch_mprintf("%s", serialized_string
);
384 free(serialized_string
);
385 serialized_string
= new_serialized_string
;
386 return serialized_string
;
394 SWITCH_DECLARE(bool) Event::fire(void)
400 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Not My event!\n");
405 switch_event_t
*new_event
;
406 if (switch_event_dup(&new_event
, event
) == SWITCH_STATUS_SUCCESS
) {
407 if (switch_event_fire(&new_event
) != SWITCH_STATUS_SUCCESS
) {
408 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Failed to fire the event!\n");
409 switch_event_destroy(&new_event
);
414 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Failed to dup the event!\n");
417 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Trying to fire an event that does not exist!\n");
422 SWITCH_DECLARE(bool) Event::setPriority(switch_priority_t priority
)
427 switch_event_set_priority(event
, priority
);
430 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Trying to setPriority an event that does not exist!\n");
435 SWITCH_DECLARE(const char *)Event::getHeader(const char *header_name
)
439 if (zstr(header_name
)) {
440 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Trying to getHeader an invalid header!\n");
445 return switch_event_get_header(event
, header_name
);
447 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Trying to getHeader an event that does not exist!\n");
452 SWITCH_DECLARE(bool) Event::addHeader(const char *header_name
, const char *value
)
457 return switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, header_name
, value
) == SWITCH_STATUS_SUCCESS
? true : false;
459 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Trying to addHeader an event that does not exist!\n");
465 SWITCH_DECLARE(bool) Event::delHeader(const char *header_name
)
469 if (zstr(header_name
)) {
470 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Trying to delHeader an invalid header!\n");
475 return switch_event_del_header(event
, header_name
) == SWITCH_STATUS_SUCCESS
? true : false;
477 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Trying to delHeader an event that does not exist!\n");
484 SWITCH_DECLARE(bool) Event::addBody(const char *value
)
489 return switch_event_add_body(event
, "%s", value
) == SWITCH_STATUS_SUCCESS
? true : false;
491 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Trying to addBody an event that does not exist!\n");
497 SWITCH_DECLARE(char *)Event::getBody(void)
500 this_check((char *)"");
503 return switch_event_get_body(event
);
505 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Trying to getBody an event that does not exist!\n");
511 SWITCH_DECLARE(const char *)Event::getType(void)
516 return switch_event_name(event
->event_id
);
518 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Trying to getType an event that does not exist!\n");
521 return (char *) "invalid";
524 SWITCH_DECLARE(bool)Event::merge(Event
*to_merge
)
529 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Trying to merge to an event that does not exist!\n");
533 if (!to_merge
|| !to_merge
->event
) {
534 switch_log_printf(SWITCH_CHANNEL_LOG
,SWITCH_LOG_ERROR
, "Trying to merge from an event that does not exist!\n");
538 switch_event_merge(event
, to_merge
->event
);
543 SWITCH_DECLARE_CONSTRUCTOR
DTMF::DTMF(char idigit
, uint32_t iduration
)
547 if (iduration
== 0) {
548 iduration
= SWITCH_DEFAULT_DTMF_DURATION
;
551 duration
= iduration
;
554 SWITCH_DECLARE_CONSTRUCTOR
DTMF::~DTMF()
560 SWITCH_DECLARE_CONSTRUCTOR
Stream::Stream()
562 SWITCH_STANDARD_STREAM(mystream
);
563 stream_p
= &mystream
;
567 SWITCH_DECLARE_CONSTRUCTOR
Stream::Stream(switch_stream_handle_t
*sp
)
574 SWITCH_DECLARE_CONSTRUCTOR
Stream::~Stream()
577 switch_safe_free(mystream
.data
);
581 /* WARNING!! you are not encouraged to use this unless you understand the risk!!! */
582 SWITCH_DECLARE(const char *) Stream::read(int *len
)
588 if (!stream_p
->read_function
) return NULL
;
590 buff
= stream_p
->read_function(stream_p
, len
);
592 if (!buff
|| *len
<= 0) {
597 return (const char *)buff
;
600 SWITCH_DECLARE(void) Stream::write(const char *data
)
603 stream_p
->write_function(stream_p
, "%s", data
);
606 SWITCH_DECLARE(void) Stream::raw_write(const char *data
, int len
)
609 stream_p
->raw_write_function(stream_p
, (uint8_t *)data
, len
);
612 SWITCH_DECLARE(const char *)Stream::get_data()
616 return stream_p
? (const char *)stream_p
->data
: NULL
;
620 SWITCH_DECLARE_CONSTRUCTOR
CoreSession::CoreSession()
625 SWITCH_DECLARE_CONSTRUCTOR
CoreSession::CoreSession(char *nuuid
, CoreSession
*a_leg
)
627 switch_channel_t
*other_channel
= NULL
;
631 if (a_leg
&& a_leg
->session
) {
632 other_channel
= switch_core_session_get_channel(a_leg
->session
);
635 if (!strchr(nuuid
, '/') && (session
= switch_core_session_force_locate(nuuid
))) {
636 uuid
= strdup(nuuid
);
637 channel
= switch_core_session_get_channel(session
);
640 cause
= SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
;
641 if (switch_ivr_originate(a_leg
? a_leg
->session
: NULL
, &session
, &cause
, nuuid
, 60, NULL
, NULL
, NULL
, NULL
, NULL
, SOF_NONE
, NULL
, NULL
)
642 == SWITCH_STATUS_SUCCESS
) {
643 channel
= switch_core_session_get_channel(session
);
645 switch_set_flag(this, S_HUP
);
646 uuid
= strdup(switch_core_session_get_uuid(session
));
647 switch_channel_set_state(switch_core_session_get_channel(session
), CS_SOFT_EXECUTE
);
648 switch_channel_wait_for_state(channel
, other_channel
, CS_SOFT_EXECUTE
);
653 SWITCH_DECLARE_CONSTRUCTOR
CoreSession::CoreSession(switch_core_session_t
*new_session
)
657 if (new_session
&& switch_core_session_read_lock_hangup(new_session
) == SWITCH_STATUS_SUCCESS
) {
658 session
= new_session
;
659 channel
= switch_core_session_get_channel(session
);
661 uuid
= strdup(switch_core_session_get_uuid(session
));
665 SWITCH_DECLARE_CONSTRUCTOR
CoreSession::~CoreSession()
668 if (allocated
) destroy();
671 SWITCH_DECLARE(char *) CoreSession::getXMLCDR()
674 switch_xml_t cdr
= NULL
;
676 this_check((char *)"");
677 sanity_check((char *)"");
679 switch_safe_free(xml_cdr_text
);
681 if (switch_ivr_generate_xml_cdr(session
, &cdr
) == SWITCH_STATUS_SUCCESS
) {
682 xml_cdr_text
= switch_xml_toxml(cdr
, SWITCH_FALSE
);
683 switch_xml_free(cdr
);
686 return (char *) (xml_cdr_text
? xml_cdr_text
: "");
689 SWITCH_DECLARE(void) CoreSession::setEventData(Event
*e
)
692 sanity_check_noreturn
;
694 if (channel
&& e
->event
) {
695 switch_channel_event_set_data(channel
, e
->event
);
699 SWITCH_DECLARE(int) CoreSession::answer()
701 switch_status_t status
;
704 status
= switch_channel_answer(channel
);
705 return status
== SWITCH_STATUS_SUCCESS
? 1 : 0;
709 SWITCH_DECLARE(int) CoreSession::print(char *txt
)
711 switch_status_t status
;
712 status
= switch_core_session_print(session
, switch_str_nil(txt
));
715 return status
== SWITCH_STATUS_SUCCESS
? 1 : 0;
718 SWITCH_DECLARE(int) CoreSession::insertFile(const char *file
, const char *insert_file
, int sample_point
)
720 switch_status_t status
;
723 status
= switch_ivr_insert_file(session
, file
, insert_file
, (switch_size_t
)sample_point
);
724 return status
== SWITCH_STATUS_SUCCESS
? 1 : 0;
727 SWITCH_DECLARE(int) CoreSession::preAnswer()
729 switch_status_t status
;
732 status
= switch_channel_pre_answer(channel
);
733 return status
== SWITCH_STATUS_SUCCESS
? 1 : 0;
736 SWITCH_DECLARE(void) CoreSession::hangupState(void)
738 sanity_check_noreturn
;
739 this->begin_allow_threads();
740 if (switch_channel_down(channel
)) {
741 switch_core_session_hangup_state(session
, SWITCH_FALSE
);
743 this->end_allow_threads();
746 SWITCH_DECLARE(void) CoreSession::hangup(const char *cause
)
749 sanity_check_noreturn
;
750 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "CoreSession::hangup\n");
751 this->begin_allow_threads();
752 switch_channel_hangup(channel
, switch_channel_str2cause(cause
));
753 this->end_allow_threads();
756 SWITCH_DECLARE(void) CoreSession::setPrivate(char *var
, void *val
)
759 sanity_check_noreturn
;
760 switch_channel_set_private(channel
, var
, val
);
763 SWITCH_DECLARE(void *)CoreSession::getPrivate(char *var
)
767 return switch_channel_get_private(channel
, var
);
770 SWITCH_DECLARE(void) CoreSession::setVariable(char *var
, char *val
)
773 sanity_check_noreturn
;
774 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "CoreSession::setVariable('%s', '%s')\n", var
, val
);
775 switch_channel_set_variable_var_check(channel
, var
, val
, SWITCH_FALSE
);
778 SWITCH_DECLARE(const char *)CoreSession::getVariable(char *var
)
782 return switch_channel_get_variable(channel
, var
);
785 SWITCH_DECLARE(void) CoreSession::execute(const char *app
, const char *data
)
788 sanity_check_noreturn
;
791 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No application specified\n");
795 begin_allow_threads();
796 switch_core_session_execute_application(session
, app
, data
);
800 SWITCH_DECLARE(void) CoreSession::setDTMFCallback(void *cbfunc
, char *funcargs
) {
803 sanity_check_noreturn
;
805 cb_state
.funcargs
= funcargs
;
806 cb_state
.function
= cbfunc
;
808 args
.buf
= &cb_state
;
809 args
.buflen
= sizeof(cb_state
); // not sure what this is used for, copy mod_spidermonkey
811 switch_channel_set_private(channel
, "CoreSession", this);
813 // we cannot set the actual callback to a python function, because
814 // the callback is a function pointer with a specific signature.
815 // so, set it to the following c function which will act as a proxy,
816 // finding the python callback in the args callback args structure
817 args
.input_callback
= dtmf_callback
;
823 SWITCH_DECLARE(void) CoreSession::sendEvent(Event
*sendME
)
826 sanity_check_noreturn
;
829 switch_event_t
*new_event
;
830 if (switch_event_dup(&new_event
, sendME
->event
) == SWITCH_STATUS_SUCCESS
) {
831 switch_core_session_receive_event(session
, &new_event
);
836 SWITCH_DECLARE(int) CoreSession::speak(char *text
)
838 switch_status_t status
;
844 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No TTS engine specified\n");
845 return SWITCH_STATUS_FALSE
;
849 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No TTS voice specified\n");
850 return SWITCH_STATUS_FALSE
;
854 begin_allow_threads();
855 status
= switch_ivr_speak_text(session
, tts_name
, voice_name
, text
, ap
);
857 return status
== SWITCH_STATUS_SUCCESS
? 1 : 0;
860 SWITCH_DECLARE(void) CoreSession::set_tts_parms(char *tts_name_p
, char *voice_name_p
)
862 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "set_tts_parms is deprecated. Use set_tts_params.\n");
864 sanity_check_noreturn
;
865 switch_safe_free(tts_name
);
866 switch_safe_free(voice_name
);
867 tts_name
= strdup(tts_name_p
);
868 voice_name
= strdup(voice_name_p
);
871 SWITCH_DECLARE(void) CoreSession::set_tts_params(char *tts_name_p
, char *voice_name_p
)
874 sanity_check_noreturn
;
875 switch_safe_free(tts_name
);
876 switch_safe_free(voice_name
);
877 tts_name
= strdup(switch_str_nil(tts_name_p
));
878 voice_name
= strdup(switch_str_nil(voice_name_p
));
881 SWITCH_DECLARE(int) CoreSession::collectDigits(int abs_timeout
) {
882 return collectDigits(0, abs_timeout
);
885 SWITCH_DECLARE(int) CoreSession::collectDigits(int digit_timeout
, int abs_timeout
) {
888 begin_allow_threads();
889 switch_ivr_collect_digits_callback(session
, ap
, digit_timeout
, abs_timeout
);
891 return SWITCH_STATUS_SUCCESS
;
894 SWITCH_DECLARE(char *) CoreSession::getDigits(int maxdigits
, char *terminators
, int timeout
)
896 return getDigits(maxdigits
, terminators
, timeout
, 0);
899 SWITCH_DECLARE(char *) CoreSession::getDigits(int maxdigits
, char *terminators
, int timeout
, int interdigit
)
901 return getDigits(maxdigits
, terminators
, timeout
, interdigit
, 0);
904 SWITCH_DECLARE(char *) CoreSession::getDigits(int maxdigits
,
910 this_check((char *)"");
911 sanity_check((char *)"");
912 begin_allow_threads();
915 memset(dtmf_buf
, 0, sizeof(dtmf_buf
));
916 switch_ivr_collect_digits_count(session
,
922 (uint32_t) timeout
, (uint32_t)interdigit
, (uint32_t)abstimeout
);
924 /* Only log DTMF buffer if sensitive_dtmf channel variable not set to true */
925 if (!(switch_channel_var_true(switch_core_session_get_channel(session
), SWITCH_SENSITIVE_DTMF_VARIABLE
))) {
926 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "getDigits dtmf_buf: %s\n", dtmf_buf
);
933 SWITCH_DECLARE(int) CoreSession::transfer(char *extension
, char *dialplan
, char *context
)
935 switch_status_t status
;
938 begin_allow_threads();
939 status
= switch_ivr_session_transfer(session
, extension
, dialplan
, context
);
940 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "transfer result: %d\n", status
);
942 return status
== SWITCH_STATUS_SUCCESS
? 1 : 0;
946 SWITCH_DECLARE(char *) CoreSession::read(int min_digits
,
948 const char *prompt_audio_file
,
950 const char *valid_terminators
,
953 this_check((char *)"");
954 sanity_check((char *)"");
955 if (min_digits
< 1) {
959 if (max_digits
< 1) {
967 begin_allow_threads();
968 switch_ivr_read(session
, min_digits
, max_digits
, prompt_audio_file
, NULL
, dtmf_buf
,
969 sizeof(dtmf_buf
), timeout
, valid_terminators
, (uint32_t)digit_timeout
);
975 SWITCH_DECLARE(char *) CoreSession::playAndGetDigits(int min_digits
,
981 char *bad_input_audio_files
,
983 const char *var_name
,
985 const char *transfer_on_failure
)
987 sanity_check((char *)"");
988 this_check((char *)"");
989 begin_allow_threads();
990 memset(dtmf_buf
, 0, sizeof(dtmf_buf
));
991 switch_play_and_get_digits( session
,
992 (uint32_t) min_digits
,
993 (uint32_t) max_digits
,
994 (uint32_t) max_tries
,
998 bad_input_audio_files
,
1003 (uint32_t) digit_timeout
,
1004 transfer_on_failure
);
1006 end_allow_threads();
1010 SWITCH_DECLARE(void) CoreSession::detectSpeech(char *arg0
, char *arg1
, char *arg2
, char *arg3
)
1013 sanity_check_noreturn
;
1015 begin_allow_threads();
1019 if (!strcasecmp(arg0
, "grammar") && arg1
&& arg2
) {
1020 switch_ivr_detect_speech_load_grammar(session
, arg1
, arg2
);
1021 } else if (!strcasecmp(arg0
, "nogrammar") && arg1
) {
1022 switch_ivr_detect_speech_unload_grammar(session
, arg1
);
1023 } else if (!strcasecmp(arg0
, "grammaron") && arg1
) {
1024 switch_ivr_detect_speech_enable_grammar(session
, arg1
);
1025 } else if (!strcasecmp(arg0
, "grammaroff") && arg1
) {
1026 switch_ivr_detect_speech_disable_grammar(session
, arg1
);
1027 } else if (!strcasecmp(arg0
, "grammarsalloff")) {
1028 switch_ivr_detect_speech_disable_all_grammars(session
);
1029 } else if (!strcasecmp(arg0
, "init") && arg1
&& arg2
) {
1030 switch_ivr_detect_speech_init(session
, arg1
, arg2
, NULL
);
1031 } else if (!strcasecmp(arg0
, "pause")) {
1032 switch_ivr_pause_detect_speech(session
);
1033 } else if (!strcasecmp(arg0
, "resume")) {
1034 switch_ivr_resume_detect_speech(session
);
1035 } else if (!strcasecmp(arg0
, "stop")) {
1036 switch_ivr_stop_detect_speech(session
);
1037 } else if (!strcasecmp(arg0
, "param") && arg1
&& arg2
) {
1038 switch_ivr_set_param_detect_speech(session
, arg1
, arg2
);
1039 } else if (!strcasecmp(arg0
, "start-input-timers")) {
1040 switch_ivr_detect_speech_start_input_timers(session
);
1041 } else if (!strcasecmp(arg0
, "start_input_timers")) {
1042 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "start_input_timers is deprecated, please use start-input-timers instead!\n");
1043 switch_ivr_detect_speech_start_input_timers(session
);
1044 } else if (arg1
&& arg2
&& arg3
) {
1045 switch_ivr_detect_speech(session
, arg0
, arg1
, arg2
, arg3
, NULL
);
1048 end_allow_threads();
1051 SWITCH_DECLARE(char *) CoreSession::playAndDetectSpeech(char *file
, char *engine
, char *grammar
)
1053 sanity_check((char *)"");
1054 this_check((char *)"");
1055 begin_allow_threads();
1057 char *result
= NULL
;
1059 switch_status_t status
= switch_ivr_play_and_detect_speech(session
, file
, engine
, grammar
, &result
, 0, ap
);
1060 if (status
== SWITCH_STATUS_SUCCESS
) {
1062 } else if (status
== SWITCH_STATUS_GENERR
) {
1063 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "GRAMMAR ERROR\n");
1064 } else if (status
== SWITCH_STATUS_NOT_INITALIZED
) {
1065 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "ASR INIT ERROR\n");
1067 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "ERROR status = %d\n", status
);
1070 end_allow_threads();
1072 return result
? strdup(result
) : NULL
; // remeber to free me
1075 SWITCH_DECLARE(void) CoreSession::say(const char *tosay
, const char *module_name
, const char *say_type
, const char *say_method
, const char *say_gender
)
1078 sanity_check_noreturn
;
1079 if (!(tosay
&& module_name
&& say_type
&& say_method
)) {
1080 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Error! invalid args.\n");
1083 begin_allow_threads();
1084 switch_ivr_say(session
, tosay
, module_name
, say_type
, say_method
, say_gender
, ap
);
1085 end_allow_threads();
1088 SWITCH_DECLARE(void) CoreSession::sayPhrase(const char *phrase_name
, const char *phrase_data
, const char *phrase_lang
)
1091 sanity_check_noreturn
;
1093 if (!(phrase_name
)) {
1094 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Error! invalid args.\n");
1098 begin_allow_threads();
1099 switch_ivr_phrase_macro(session
, phrase_name
, phrase_data
, phrase_lang
, ap
);
1100 end_allow_threads();
1103 SWITCH_DECLARE(int) CoreSession::streamFile(char *file
, int starting_sample_count
) {
1105 switch_status_t status
;
1106 //switch_file_handle_t fh = { 0 };
1108 switch_file_handle_t local_fh
;
1113 memset(&local_fh
, 0, sizeof(local_fh
));
1115 local_fh
.samples
= starting_sample_count
;
1118 if ((prebuf
= switch_channel_get_variable(this->channel
, "stream_prebuffer"))) {
1119 int maybe
= atoi(prebuf
);
1121 local_fh
.prebuf
= maybe
;
1125 begin_allow_threads();
1126 status
= switch_ivr_play_file(session
, fhp
, file
, ap
);
1127 end_allow_threads();
1131 return status
== SWITCH_STATUS_SUCCESS
? 1 : 0;
1135 SWITCH_DECLARE(int) CoreSession::sleep(int ms
, int sync
) {
1137 switch_status_t status
;
1142 begin_allow_threads();
1143 status
= switch_ivr_sleep(session
, ms
, (switch_bool_t
) sync
, ap
);
1144 end_allow_threads();
1146 return status
== SWITCH_STATUS_SUCCESS
? 1 : 0;
1150 SWITCH_DECLARE(bool) CoreSession::ready() {
1157 sanity_check(false);
1159 return switch_channel_ready(channel
) != 0;
1163 SWITCH_DECLARE(bool) CoreSession::bridged() {
1170 sanity_check(false);
1172 return (switch_channel_up(channel
) && switch_channel_test_flag(channel
, CF_BRIDGED
));
1175 SWITCH_DECLARE(bool) CoreSession::mediaReady() {
1178 sanity_check(false);
1179 return switch_channel_media_ready(channel
) != 0;
1182 SWITCH_DECLARE(bool) CoreSession::answered() {
1185 sanity_check(false);
1186 return switch_channel_test_flag(channel
, CF_ANSWERED
) != 0;
1189 SWITCH_DECLARE(void) CoreSession::destroy(void)
1199 switch_safe_free(xml_cdr_text
);
1200 switch_safe_free(uuid
);
1201 switch_safe_free(tts_name
);
1202 switch_safe_free(voice_name
);
1206 channel
= switch_core_session_get_channel(session
);
1210 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
,
1211 "%s destroy/unlink session from object\n", switch_channel_get_name(channel
));
1212 switch_channel_set_private(channel
, "CoreSession", NULL
);
1213 if (switch_channel_up(channel
) && switch_test_flag(this, S_HUP
) && !switch_channel_test_flag(channel
, CF_TRANSFER
)) {
1214 switch_channel_hangup(channel
, SWITCH_CAUSE_NORMAL_CLEARING
);
1218 switch_core_session_rwunlock(session
);
1227 SWITCH_DECLARE(const char *) CoreSession::hangupCause()
1230 return switch_channel_cause2str(cause
);
1233 SWITCH_DECLARE(const char *) CoreSession::getState()
1238 return switch_channel_state_name(switch_channel_get_state(channel
));
1245 SWITCH_DECLARE(int) CoreSession::originate(CoreSession
*a_leg_session
, char *dest
, int timeout
, switch_state_handler_table_t
*handlers
)
1248 switch_core_session_t
*aleg_core_session
= NULL
;
1252 cause
= SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
;
1254 if (a_leg_session
!= NULL
) {
1255 aleg_core_session
= a_leg_session
->session
;
1258 // this session has no valid switch_core_session_t at this point, and therefore
1259 // no valid channel. since the threadstate is stored in the channel, and there
1260 // is none, if we try to call begin_alllow_threads it will fail miserably.
1261 // use the 'a leg session' to do the thread swapping stuff.
1262 if (a_leg_session
) a_leg_session
->begin_allow_threads();
1264 if (switch_ivr_originate(aleg_core_session
,
1276 NULL
) != SWITCH_STATUS_SUCCESS
) {
1277 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "Error Creating Outgoing Channel! [%s]\n", dest
);
1282 if (a_leg_session
) a_leg_session
->end_allow_threads();
1283 channel
= switch_core_session_get_channel(session
);
1285 switch_safe_free(uuid
);
1286 uuid
= strdup(switch_core_session_get_uuid(session
));
1287 switch_channel_set_state(switch_core_session_get_channel(session
), CS_SOFT_EXECUTE
);
1289 return SWITCH_STATUS_SUCCESS
;
1292 if (a_leg_session
) a_leg_session
->end_allow_threads();
1293 return SWITCH_STATUS_FALSE
;
1296 SWITCH_DECLARE(int) CoreSession::recordFile(char *file_name
, int time_limit
, int silence_threshold
, int silence_hits
)
1298 switch_status_t status
;
1299 switch_file_handle_t local_fh
;
1304 if (!file_name
) return 0;
1305 memset(&local_fh
, 0, sizeof(local_fh
));
1307 local_fh
.thresh
= silence_threshold
;
1308 local_fh
.silence_hits
= silence_hits
;
1310 begin_allow_threads();
1311 status
= switch_ivr_record_file(session
, &local_fh
, file_name
, ap
, time_limit
);
1312 end_allow_threads();
1316 return status
== SWITCH_STATUS_SUCCESS
? 1 : 0;
1320 SWITCH_DECLARE(int) CoreSession::flushEvents()
1322 switch_event_t
*event
;
1328 return SWITCH_STATUS_FALSE
;
1331 while (switch_core_session_dequeue_event(session
, &event
, SWITCH_TRUE
) == SWITCH_STATUS_SUCCESS
) {
1332 switch_event_destroy(&event
);
1334 return SWITCH_STATUS_SUCCESS
;
1337 SWITCH_DECLARE(int) CoreSession::flushDigits()
1341 switch_channel_flush_dtmf(switch_core_session_get_channel(session
));
1342 return SWITCH_STATUS_SUCCESS
;
1345 SWITCH_DECLARE(int) CoreSession::setAutoHangup(bool val
)
1351 return SWITCH_STATUS_FALSE
;
1354 switch_set_flag(this, S_HUP
);
1356 switch_clear_flag(this, S_HUP
);
1358 return SWITCH_STATUS_SUCCESS
;
1361 SWITCH_DECLARE(void) CoreSession::waitForAnswer(CoreSession
*calling_session
)
1364 sanity_check_noreturn
;
1366 switch_ivr_wait_for_answer(calling_session
? calling_session
->session
: NULL
, session
);
1370 SWITCH_DECLARE(void) CoreSession::setHangupHook(void *hangup_func
) {
1373 sanity_check_noreturn
;
1375 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "CoreSession::seHangupHook, hangup_func: %p\n", hangup_func
);
1376 on_hangup
= hangup_func
;
1377 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
1379 hook_state
= switch_channel_get_state(channel
);
1380 switch_channel_set_private(channel
, "CoreSession", this);
1381 switch_core_event_hook_add_state_change(session
, hanguphook
);
1384 SWITCH_DECLARE(void) CoreSession::consoleLog(char *level_str
, char *msg
)
1386 switch_log_level_t level
= SWITCH_LOG_DEBUG
;
1388 level
= switch_log_str2level(level_str
);
1389 if (level
== SWITCH_LOG_INVALID
) {
1390 level
= SWITCH_LOG_DEBUG
;
1393 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), level
, "%s", switch_str_nil(msg
));
1396 SWITCH_DECLARE(void) CoreSession::consoleLog2(char *level_str
, char *file
, char *func
, int line
, char *msg
)
1398 switch_log_level_t level
= SWITCH_LOG_DEBUG
;
1400 level
= switch_log_str2level(level_str
);
1401 if (level
== SWITCH_LOG_INVALID
) {
1402 level
= SWITCH_LOG_DEBUG
;
1405 switch_log_printf(SWITCH_CHANNEL_ID_SESSION
, file
, func
, line
, (const char*)session
,
1406 level
, "%s", switch_str_nil(msg
));
1409 /* ---- methods not bound to CoreSession instance ---- */
1412 SWITCH_DECLARE(int) globalSetVariable(const char *var
, const char *val
, const char *val2
)
1414 if (zstr(val
)) val
= NULL
;
1415 if (zstr(val2
)) val2
= NULL
;
1418 return switch_core_set_var_conditional(var
, val
, val2
);
1420 switch_core_set_variable(var
, val
);
1421 return SWITCH_STATUS_SUCCESS
;
1425 SWITCH_DECLARE(void) setGlobalVariable(char *var_name
, char *var_val
)
1427 switch_core_set_variable(var_name
, var_val
);
1430 SWITCH_DECLARE(char *) getGlobalVariable(char *var_name
)
1432 return switch_core_get_variable_dup(var_name
);
1436 SWITCH_DECLARE(bool) running(void)
1438 return switch_core_running() ? true : false;
1441 SWITCH_DECLARE(void) consoleLog(char *level_str
, char *msg
)
1443 return console_log(level_str
, msg
);
1446 SWITCH_DECLARE(void) consoleLog2(char *level_str
, char *file
, char *func
, int line
, char *msg
)
1448 return console_log2(level_str
, file
, func
, line
, msg
);
1451 SWITCH_DECLARE(void) consoleCleanLog(char *msg
)
1453 return console_clean_log(msg
);
1456 SWITCH_DECLARE(void) console_log(char *level_str
, char *msg
)
1458 switch_log_level_t level
= SWITCH_LOG_DEBUG
;
1460 level
= switch_log_str2level(level_str
);
1461 if (level
== SWITCH_LOG_INVALID
) {
1462 level
= SWITCH_LOG_DEBUG
;
1466 switch_log_printf(SWITCH_CHANNEL_LOG
, level
, "%s", switch_str_nil(msg
));
1469 SWITCH_DECLARE(void) console_log2(char *level_str
, char *file
, char *func
, int line
, char *msg
)
1471 switch_log_level_t level
= SWITCH_LOG_DEBUG
;
1473 level
= switch_log_str2level(level_str
);
1474 if (level
== SWITCH_LOG_INVALID
) {
1475 level
= SWITCH_LOG_DEBUG
;
1478 switch_log_printf(SWITCH_CHANNEL_ID_LOG
, file
, func
, line
, NULL
, level
, "%s", switch_str_nil(msg
));
1481 SWITCH_DECLARE(void) console_clean_log(char *msg
)
1483 switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN
,SWITCH_LOG_DEBUG
, "%s", switch_str_nil(msg
));
1486 SWITCH_DECLARE(bool) email(char *to
, char *from
, char *headers
, char *body
, char *file
, char *convert_cmd
, char *convert_ext
)
1488 if (switch_simple_email(to
, from
, headers
, body
, file
, convert_cmd
, convert_ext
) == SWITCH_TRUE
) {
1494 SWITCH_DECLARE(void) switch_msleep(unsigned ms
)
1496 switch_sleep(ms
* 1000);
1500 SWITCH_DECLARE(void) bridge(CoreSession
&session_a
, CoreSession
&session_b
)
1502 switch_input_callback_function_t dtmf_func
= NULL
;
1503 switch_input_args_t args
;
1504 switch_channel_t
*channel_a
= NULL
, *channel_b
= NULL
;
1505 const char *err
= "Channels not ready\n";
1507 if (session_a
.allocated
&& session_a
.session
&& session_b
.allocated
&& session_b
.session
) {
1508 channel_a
= switch_core_session_get_channel(session_a
.session
);
1509 channel_b
= switch_core_session_get_channel(session_b
.session
);
1511 if (switch_channel_ready(channel_a
) && switch_channel_ready(channel_b
)) {
1512 session_a
.begin_allow_threads();
1513 if (switch_channel_direction(channel_a
) == SWITCH_CALL_DIRECTION_INBOUND
&& !switch_channel_media_ready(channel_a
)) {
1514 switch_channel_pre_answer(channel_a
);
1517 if (switch_channel_ready(channel_a
) && switch_channel_ready(channel_b
)) {
1518 args
= session_a
.get_cb_args(); // get the cb_args data structure for session a
1519 dtmf_func
= args
.input_callback
; // get the call back function
1521 switch_ivr_multi_threaded_bridge(session_a
.session
, session_b
.session
, dtmf_func
, args
.buf
, args
.buf
);
1523 session_a
.end_allow_threads();
1528 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a
.session
), SWITCH_LOG_ERROR
, "%s", err
);
1534 SWITCH_DECLARE_NONSTD(switch_status_t
) hanguphook(switch_core_session_t
*session_hungup
)
1536 if (session_hungup
) {
1537 switch_channel_t
*channel
= switch_core_session_get_channel(session_hungup
);
1538 CoreSession
*coresession
= NULL
;
1539 switch_channel_state_t state
= switch_channel_get_state(channel
);
1541 if ((coresession
= (CoreSession
*) switch_channel_get_private(channel
, "CoreSession"))) {
1542 if (coresession
->hook_state
!= state
) {
1543 coresession
->cause
= switch_channel_get_cause(channel
);
1544 coresession
->hook_state
= state
;
1545 coresession
->check_hangup_hook();
1549 return SWITCH_STATUS_SUCCESS
;
1551 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "hangup hook called with null session, something is horribly wrong\n");
1552 return SWITCH_STATUS_FALSE
;
1557 SWITCH_DECLARE_NONSTD(switch_status_t
) dtmf_callback(switch_core_session_t
*session_cb
,
1559 switch_input_type_t itype
,
1561 unsigned int buflen
) {
1563 switch_channel_t
*channel
= switch_core_session_get_channel(session_cb
);
1564 CoreSession
*coresession
= NULL
;
1566 coresession
= (CoreSession
*) switch_channel_get_private(channel
, "CoreSession");
1569 return SWITCH_STATUS_FALSE
;
1572 return coresession
->run_dtmf_callback(input
, itype
);
1576 SWITCH_DECLARE(switch_status_t
) CoreSession::process_callback_result(char *result
)
1579 this_check(SWITCH_STATUS_FALSE
);
1580 sanity_check(SWITCH_STATUS_FALSE
);
1582 return switch_ivr_process_fh(session
, result
, fhp
);
1588 * indent-tabs-mode:t
1593 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: