]>
Commit | Line | Data |
---|---|---|
03845667 MJ |
1 | /* |
2 | * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application | |
3 | * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com> | |
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 <anthmct@yahoo.com> | |
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 <anthmct@yahoo.com> | |
27 | * | |
28 | * | |
29 | * switch_cpp.cpp -- C++ wrapper | |
30 | * | |
31 | */ | |
32 | ||
83f84876 AM |
33 | #include <switch.h> |
34 | #include <switch_cpp.h> | |
35 | ||
8107c49a MJ |
36 | #ifdef _MSC_VER |
37 | #pragma warning(disable:4127 4003) | |
38 | #endif | |
39 | ||
e028f269 | 40 | |
069d4681 | 41 | SWITCH_DECLARE_CONSTRUCTOR Event::Event(const char *type, const char *subclass_name) |
ae76db7b AM |
42 | { |
43 | switch_event_types_t event_id; | |
59526679 | 44 | |
ae76db7b AM |
45 | if (switch_name_event(type, &event_id) != SWITCH_STATUS_SUCCESS) { |
46 | event_id = SWITCH_EVENT_MESSAGE; | |
47 | } | |
48 | ||
49 | switch_event_create_subclass(&event, event_id, subclass_name); | |
59526679 AM |
50 | serialized_string = NULL; |
51 | mine = 1; | |
52 | } | |
53 | ||
069d4681 | 54 | SWITCH_DECLARE_CONSTRUCTOR Event::Event(switch_event_t *wrap_me, int free_me) |
59526679 AM |
55 | { |
56 | event = wrap_me; | |
57 | mine = free_me; | |
58 | serialized_string = NULL; | |
ae76db7b AM |
59 | } |
60 | ||
069d4681 | 61 | SWITCH_DECLARE_CONSTRUCTOR Event::~Event() |
ae76db7b | 62 | { |
59526679 AM |
63 | |
64 | if (serialized_string) { | |
65 | free(serialized_string); | |
66 | } | |
67 | ||
68 | if (event && mine) { | |
ae76db7b AM |
69 | switch_event_destroy(&event); |
70 | } | |
71 | } | |
72 | ||
59526679 | 73 | |
069d4681 | 74 | SWITCH_DECLARE(const char *)Event::serialize(const char *format) |
59526679 AM |
75 | { |
76 | int isxml = 0; | |
77 | ||
78 | if (serialized_string) { | |
79 | free(serialized_string); | |
80 | } | |
81 | ||
82 | if (!event) { | |
83 | return ""; | |
84 | } | |
85 | ||
86 | if (format && !strcasecmp(format, "xml")) { | |
87 | isxml++; | |
88 | } | |
89 | ||
90 | if (isxml) { | |
91 | switch_xml_t xml; | |
59526679 AM |
92 | if ((xml = switch_event_xmlize(event, SWITCH_VA_NONE))) { |
93 | serialized_string = switch_xml_toxml(xml, SWITCH_FALSE); | |
94 | switch_xml_free(xml); | |
95 | return serialized_string; | |
96 | } else { | |
97 | return ""; | |
98 | } | |
99 | } else { | |
100 | if (switch_event_serialize(event, &serialized_string, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { | |
101 | return serialized_string; | |
102 | } | |
103 | } | |
104 | ||
105 | return ""; | |
106 | ||
107 | } | |
108 | ||
069d4681 | 109 | SWITCH_DECLARE(bool) Event::fire(void) |
ae76db7b | 110 | { |
59526679 AM |
111 | if (!mine) { |
112 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Not My event!\n"); | |
113 | return false; | |
114 | } | |
115 | ||
ae76db7b AM |
116 | if (event) { |
117 | switch_event_fire(&event); | |
118 | return true; | |
119 | } | |
120 | return false; | |
121 | } | |
122 | ||
069d4681 | 123 | SWITCH_DECLARE(bool) Event::set_priority(switch_priority_t priority) |
ae76db7b AM |
124 | { |
125 | if (event) { | |
126 | switch_event_set_priority(event, priority); | |
127 | return true; | |
128 | } | |
129 | return false; | |
130 | } | |
131 | ||
069d4681 | 132 | SWITCH_DECLARE(char *)Event::get_header(char *header_name) |
ae76db7b AM |
133 | { |
134 | if (event) { | |
135 | return switch_event_get_header(event, header_name); | |
136 | } | |
137 | return NULL; | |
138 | } | |
139 | ||
069d4681 | 140 | SWITCH_DECLARE(bool) Event::add_header(const char *header_name, const char *value) |
ae76db7b AM |
141 | { |
142 | if (event) { | |
143 | return switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header_name, value) == SWITCH_STATUS_SUCCESS ? true : false; | |
144 | } | |
145 | ||
146 | return false; | |
147 | } | |
148 | ||
069d4681 | 149 | SWITCH_DECLARE(bool) Event::del_header(const char *header_name) |
ae76db7b AM |
150 | { |
151 | if (event) { | |
152 | return switch_event_del_header(event, header_name) == SWITCH_STATUS_SUCCESS ? true : false; | |
153 | } | |
154 | ||
155 | return false; | |
156 | } | |
157 | ||
158 | ||
069d4681 | 159 | SWITCH_DECLARE(bool) Event::add_body(const char *value) |
ae76db7b AM |
160 | { |
161 | if (event) { | |
162 | return switch_event_add_body(event, "%s", value) == SWITCH_STATUS_SUCCESS ? true : false; | |
163 | } | |
164 | ||
165 | return false; | |
166 | } | |
167 | ||
069d4681 | 168 | SWITCH_DECLARE(char *)Event::get_body(void) |
ae76db7b AM |
169 | { |
170 | if (event) { | |
171 | return switch_event_get_body(event); | |
172 | } | |
173 | ||
174 | return NULL; | |
175 | } | |
176 | ||
069d4681 | 177 | SWITCH_DECLARE_CONSTRUCTOR Stream::Stream() |
ae76db7b AM |
178 | { |
179 | SWITCH_STANDARD_STREAM(mystream); | |
180 | stream_p = &mystream; | |
181 | mine = 1; | |
182 | } | |
183 | ||
069d4681 | 184 | SWITCH_DECLARE_CONSTRUCTOR Stream::Stream(switch_stream_handle_t *sp) |
ae76db7b AM |
185 | { |
186 | stream_p = sp; | |
187 | mine = 0; | |
188 | } | |
189 | ||
190 | ||
069d4681 | 191 | SWITCH_DECLARE_CONSTRUCTOR Stream::~Stream() |
ae76db7b AM |
192 | { |
193 | if (mine) { | |
194 | switch_safe_free(mystream.data); | |
195 | } | |
196 | } | |
197 | ||
069d4681 | 198 | SWITCH_DECLARE(void) Stream::write(const char *data) |
ae76db7b AM |
199 | { |
200 | stream_p->write_function(stream_p, "%s", data); | |
201 | } | |
202 | ||
069d4681 | 203 | SWITCH_DECLARE(const char *)Stream::get_data() |
ae76db7b AM |
204 | { |
205 | return stream_p ? (const char *)stream_p->data : NULL; | |
206 | } | |
e028f269 MJ |
207 | |
208 | ||
47985c56 | 209 | SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession() |
e028f269 | 210 | { |
eb3dc7f2 MJ |
211 | session = NULL; |
212 | channel = NULL; | |
213 | uuid = NULL; | |
214 | tts_name = NULL; | |
215 | voice_name = NULL; | |
216 | memset(&args, 0, sizeof(args)); | |
217 | ap = NULL; | |
218 | on_hangup = NULL; | |
219 | cb_state.function = NULL; | |
94b22258 | 220 | |
eb3dc7f2 MJ |
221 | memset(&caller_profile, 0, sizeof(caller_profile)); |
222 | caller_profile.source = "mod_unknown"; | |
223 | caller_profile.dialplan = ""; | |
224 | caller_profile.context = ""; | |
225 | caller_profile.caller_id_name = ""; | |
226 | caller_profile.caller_id_number = ""; | |
227 | caller_profile.network_addr = ""; | |
228 | caller_profile.ani = ""; | |
229 | caller_profile.aniii = ""; | |
230 | caller_profile.rdnis = ""; | |
231 | caller_profile.username = ""; | |
232 | ||
e028f269 | 233 | } |
83f84876 | 234 | |
47985c56 | 235 | SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession(char *nuuid) |
83f84876 | 236 | { |
a06997ee AM |
237 | memset(&caller_profile, 0, sizeof(caller_profile)); |
238 | init_vars(); | |
59526679 | 239 | if (!strchr(nuuid, '/') && (session = switch_core_session_locate(nuuid))) { |
94b22258 | 240 | uuid = strdup(nuuid); |
d895c81d | 241 | channel = switch_core_session_get_channel(session); |
94b22258 | 242 | allocated = 1; |
ae76db7b AM |
243 | } else { |
244 | switch_call_cause_t cause; | |
245 | if (switch_ivr_originate(NULL, &session, &cause, nuuid, 60, NULL, NULL, NULL, NULL, SOF_NONE) == SWITCH_STATUS_SUCCESS) { | |
d895c81d | 246 | channel = switch_core_session_get_channel(session); |
ae76db7b AM |
247 | allocated = 1; |
248 | switch_set_flag(this, S_HUP); | |
249 | uuid = strdup(switch_core_session_get_uuid(session)); | |
250 | switch_channel_set_state(switch_core_session_get_channel(session), CS_TRANSMIT); | |
251 | } | |
252 | } | |
83f84876 AM |
253 | } |
254 | ||
47985c56 | 255 | SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession(switch_core_session_t *new_session) |
83f84876 | 256 | { |
eb3dc7f2 | 257 | memset(&caller_profile, 0, sizeof(caller_profile)); |
83f84876 | 258 | init_vars(); |
6d1f4f6d MJ |
259 | if (new_session) { |
260 | session = new_session; | |
261 | channel = switch_core_session_get_channel(session); | |
262 | allocated = 1; | |
263 | switch_core_session_read_lock(session); | |
264 | } | |
83f84876 AM |
265 | } |
266 | ||
47985c56 | 267 | SWITCH_DECLARE_CONSTRUCTOR CoreSession::~CoreSession() |
83f84876 | 268 | { |
e49f38e8 | 269 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CoreSession::~CoreSession desctructor\n"); |
6f78befa | 270 | switch_channel_t *channel = NULL; |
83f84876 AM |
271 | |
272 | if (session) { | |
6f78befa | 273 | channel = switch_core_session_get_channel(session); |
482badff | 274 | if (switch_test_flag(this, S_HUP)) { |
6f78befa TL |
275 | switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); |
276 | } | |
83f84876 AM |
277 | switch_core_session_rwunlock(session); |
278 | } | |
279 | ||
280 | switch_safe_free(uuid); | |
281 | switch_safe_free(tts_name); | |
282 | switch_safe_free(voice_name); | |
283 | } | |
284 | ||
47985c56 | 285 | SWITCH_DECLARE(int) CoreSession::answer() |
83f84876 AM |
286 | { |
287 | switch_status_t status; | |
288 | ||
289 | sanity_check(-1); | |
290 | status = switch_channel_answer(channel); | |
291 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; | |
292 | } | |
293 | ||
47985c56 | 294 | SWITCH_DECLARE(int) CoreSession::preAnswer() |
83f84876 AM |
295 | { |
296 | switch_status_t status; | |
297 | sanity_check(-1); | |
8107c49a | 298 | status = switch_channel_pre_answer(channel); |
83f84876 AM |
299 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; |
300 | } | |
301 | ||
47985c56 | 302 | SWITCH_DECLARE(void) CoreSession::hangup(char *cause) |
83f84876 | 303 | { |
f45d0601 | 304 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CoreSession::hangup\n"); |
f32f6f24 | 305 | sanity_check_noreturn; |
83f84876 AM |
306 | switch_channel_hangup(channel, switch_channel_str2cause(cause)); |
307 | } | |
308 | ||
47985c56 | 309 | SWITCH_DECLARE(void) CoreSession::setPrivate(char *var, void *val) |
59526679 AM |
310 | { |
311 | sanity_check_noreturn; | |
312 | switch_channel_set_private(channel, var, val); | |
313 | } | |
314 | ||
47985c56 | 315 | SWITCH_DECLARE(void *)CoreSession::getPrivate(char *var) |
59526679 AM |
316 | { |
317 | sanity_check(NULL); | |
318 | return switch_channel_get_private(channel, var); | |
319 | } | |
320 | ||
47985c56 | 321 | SWITCH_DECLARE(void) CoreSession::setVariable(char *var, char *val) |
83f84876 | 322 | { |
f32f6f24 | 323 | sanity_check_noreturn; |
83f84876 AM |
324 | switch_channel_set_variable(channel, var, val); |
325 | } | |
326 | ||
47985c56 | 327 | SWITCH_DECLARE(const char *)CoreSession::getVariable(char *var) |
83f84876 | 328 | { |
343d77a4 AM |
329 | sanity_check(NULL); |
330 | return switch_channel_get_variable(channel, var); | |
83f84876 AM |
331 | } |
332 | ||
47985c56 | 333 | SWITCH_DECLARE(void) CoreSession::execute(char *app, char *data) |
83f84876 AM |
334 | { |
335 | const switch_application_interface_t *application_interface; | |
f32f6f24 | 336 | sanity_check_noreturn; |
83f84876 | 337 | |
c806a20d | 338 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CoreSession::execute. app: %s data:%s\n", app, data); |
83f84876 | 339 | if ((application_interface = switch_loadable_module_get_application_interface(app))) { |
fedefcb6 | 340 | begin_allow_threads(); |
83f84876 | 341 | switch_core_session_exec(session, application_interface, data); |
fedefcb6 | 342 | end_allow_threads(); |
83f84876 AM |
343 | } |
344 | } | |
345 | ||
47985c56 | 346 | SWITCH_DECLARE(void) CoreSession::setDTMFCallback(void *cbfunc, char *funcargs) { |
6f78befa | 347 | |
a06997ee AM |
348 | sanity_check_noreturn; |
349 | ||
6f78befa TL |
350 | cb_state.funcargs = funcargs; |
351 | cb_state.function = cbfunc; | |
352 | ||
353 | args.buf = &cb_state; | |
354 | args.buflen = sizeof(cb_state); // not sure what this is used for, copy mod_spidermonkey | |
355 | ||
356 | switch_channel_set_private(channel, "CoreSession", this); | |
357 | ||
358 | // we cannot set the actual callback to a python function, because | |
359 | // the callback is a function pointer with a specific signature. | |
360 | // so, set it to the following c function which will act as a proxy, | |
361 | // finding the python callback in the args callback args structure | |
362 | args.input_callback = dtmf_callback; | |
363 | ap = &args; | |
364 | ||
365 | ||
366 | } | |
f45d0601 | 367 | |
47985c56 | 368 | SWITCH_DECLARE(void) CoreSession::sendEvent(Event *sendME) |
59526679 AM |
369 | { |
370 | if (sendME->mine) { | |
371 | switch_core_session_receive_event(session, &sendME->event); | |
372 | } else { | |
373 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Not My event!\n"); | |
374 | } | |
375 | } | |
376 | ||
47985c56 | 377 | SWITCH_DECLARE(int) CoreSession::speak(char *text) |
83f84876 AM |
378 | { |
379 | switch_status_t status; | |
83f84876 AM |
380 | |
381 | sanity_check(-1); | |
6f78befa TL |
382 | |
383 | // create and store an empty filehandle in callback args | |
384 | // to workaround a bug in the presumptuous process_callback_result() | |
385 | switch_file_handle_t fh = { 0 }; | |
386 | store_file_handle(&fh); | |
387 | ||
f45d0601 | 388 | if (!tts_name) { |
e49f38e8 | 389 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No TTS engine specified\n"); |
f45d0601 MJ |
390 | return SWITCH_STATUS_FALSE; |
391 | } | |
392 | ||
393 | if (!voice_name) { | |
e49f38e8 | 394 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No TTS voice specified\n"); |
f45d0601 MJ |
395 | return SWITCH_STATUS_FALSE; |
396 | } | |
397 | ||
160edc55 | 398 | |
fedefcb6 | 399 | begin_allow_threads(); |
160edc55 | 400 | status = switch_ivr_speak_text(session, tts_name, voice_name, text, ap); |
fedefcb6 | 401 | end_allow_threads(); |
83f84876 AM |
402 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; |
403 | } | |
404 | ||
47985c56 | 405 | SWITCH_DECLARE(void) CoreSession::set_tts_parms(char *tts_name_p, char *voice_name_p) |
83f84876 | 406 | { |
f32f6f24 | 407 | sanity_check_noreturn; |
83f84876 AM |
408 | switch_safe_free(tts_name); |
409 | switch_safe_free(voice_name); | |
410 | tts_name = strdup(tts_name_p); | |
411 | voice_name = strdup(voice_name_p); | |
412 | } | |
413 | ||
c806a20d TL |
414 | |
415 | ||
47985c56 | 416 | SWITCH_DECLARE(int) CoreSession::collectDigits(int timeout) { |
c806a20d TL |
417 | sanity_check(-1); |
418 | begin_allow_threads(); | |
419 | switch_ivr_collect_digits_callback(session, ap, timeout); | |
420 | end_allow_threads(); | |
a4301f0d | 421 | return SWITCH_STATUS_SUCCESS; |
c806a20d TL |
422 | } |
423 | ||
47985c56 | 424 | SWITCH_DECLARE(int) CoreSession::getDigits(char *dtmf_buf, |
e8f7c1b4 MJ |
425 | switch_size_t buflen, |
426 | switch_size_t maxdigits, | |
f45d0601 MJ |
427 | char *terminators, |
428 | char *terminator, | |
429 | int timeout) | |
83f84876 AM |
430 | { |
431 | switch_status_t status; | |
432 | sanity_check(-1); | |
fedefcb6 | 433 | begin_allow_threads(); |
6f78befa | 434 | |
f45d0601 MJ |
435 | status = switch_ivr_collect_digits_count(session, |
436 | dtmf_buf, | |
e8f7c1b4 MJ |
437 | buflen, |
438 | maxdigits, | |
f45d0601 MJ |
439 | terminators, |
440 | terminator, | |
df749a42 | 441 | (uint32_t) timeout, 0, 0); |
6f78befa TL |
442 | |
443 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "getDigits dtmf_buf: %s\n", dtmf_buf); | |
fedefcb6 | 444 | end_allow_threads(); |
83f84876 AM |
445 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; |
446 | } | |
447 | ||
47985c56 | 448 | SWITCH_DECLARE(int) CoreSession::transfer(char *extension, char *dialplan, char *context) |
83f84876 AM |
449 | { |
450 | switch_status_t status; | |
451 | sanity_check(-1); | |
e028f269 | 452 | begin_allow_threads(); |
83f84876 | 453 | status = switch_ivr_session_transfer(session, extension, dialplan, context); |
700aa0df | 454 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "transfer result: %d\n", status); |
e028f269 | 455 | end_allow_threads(); |
83f84876 AM |
456 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; |
457 | } | |
458 | ||
47985c56 | 459 | SWITCH_DECLARE(int) CoreSession::playAndGetDigits(int min_digits, |
f45d0601 MJ |
460 | int max_digits, |
461 | int max_tries, | |
462 | int timeout, | |
463 | char *terminators, | |
464 | char *audio_files, | |
465 | char *bad_input_audio_files, | |
466 | char *dtmf_buf, | |
467 | char *digits_regex) | |
83f84876 AM |
468 | { |
469 | switch_status_t status; | |
470 | sanity_check(-1); | |
fedefcb6 MJ |
471 | begin_allow_threads(); |
472 | status = switch_play_and_get_digits( session, | |
473 | (uint32_t) min_digits, | |
474 | (uint32_t) max_digits, | |
475 | (uint32_t) max_tries, | |
476 | (uint32_t) timeout, | |
477 | terminators, | |
478 | audio_files, | |
479 | bad_input_audio_files, | |
c806a20d TL |
480 | dtmf_buf, |
481 | 128, | |
fedefcb6 | 482 | digits_regex); |
6f78befa TL |
483 | |
484 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "playAndGetDigits dtmf_buf: %s\n", dtmf_buf); | |
485 | ||
fedefcb6 | 486 | end_allow_threads(); |
83f84876 AM |
487 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; |
488 | } | |
489 | ||
47985c56 | 490 | SWITCH_DECLARE(int) CoreSession::streamFile(char *file, int starting_sample_count) { |
f45d0601 MJ |
491 | |
492 | switch_status_t status; | |
59526679 | 493 | //switch_file_handle_t fh = { 0 }; |
622a2733 | 494 | const char *prebuf; |
f45d0601 MJ |
495 | |
496 | sanity_check(-1); | |
59526679 AM |
497 | |
498 | memset(&local_fh, 0, sizeof(local_fh)); | |
499 | fhp = &local_fh; | |
500 | local_fh.samples = starting_sample_count; | |
f45d0601 | 501 | |
f45d0601 MJ |
502 | |
503 | if ((prebuf = switch_channel_get_variable(this->channel, "stream_prebuffer"))) { | |
504 | int maybe = atoi(prebuf); | |
505 | if (maybe > 0) { | |
59526679 | 506 | local_fh.prebuf = maybe; |
f45d0601 MJ |
507 | } |
508 | } | |
509 | ||
59526679 AM |
510 | |
511 | store_file_handle(&local_fh); | |
512 | ||
513 | begin_allow_threads(); | |
514 | status = switch_ivr_play_file(session, fhp, file, ap); | |
515 | end_allow_threads(); | |
516 | ||
f45d0601 MJ |
517 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; |
518 | ||
519 | } | |
520 | ||
47985c56 | 521 | SWITCH_DECLARE(bool) CoreSession::ready() { |
f45d0601 MJ |
522 | |
523 | switch_channel_t *channel; | |
524 | ||
525 | if (!session) { | |
526 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "You must call the session.originate method before calling this method!\n"); | |
527 | return false; | |
528 | } | |
529 | ||
530 | channel = switch_core_session_get_channel(session); | |
f45d0601 | 531 | |
482badff | 532 | return switch_channel_ready(channel) != 0; |
fedefcb6 MJ |
533 | } |
534 | ||
47985c56 | 535 | SWITCH_DECLARE(int) CoreSession::originate(CoreSession *a_leg_session, |
e028f269 MJ |
536 | char *dest, |
537 | int timeout) | |
538 | { | |
539 | ||
540 | switch_memory_pool_t *pool = NULL; | |
541 | switch_core_session_t *aleg_core_session = NULL; | |
542 | switch_call_cause_t cause; | |
543 | ||
544 | cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; | |
545 | ||
700aa0df TL |
546 | if (a_leg_session != NULL) { |
547 | aleg_core_session = a_leg_session->session; | |
e028f269 MJ |
548 | } |
549 | ||
700aa0df TL |
550 | // this session has no valid switch_core_session_t at this point, and therefore |
551 | // no valid channel. since the threadstate is stored in the channel, and there | |
552 | // is none, if we try to call begin_alllow_threads it will fail miserably. | |
553 | // use the 'a leg session' to do the thread swapping stuff. | |
3d3ee88d | 554 | if (a_leg_session) a_leg_session->begin_allow_threads(); |
e028f269 MJ |
555 | |
556 | if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { | |
557 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n"); | |
558 | goto failed; | |
559 | } | |
560 | ||
561 | if (switch_ivr_originate(aleg_core_session, | |
562 | &session, | |
563 | &cause, | |
564 | dest, | |
565 | timeout, | |
566 | NULL, | |
567 | NULL, | |
568 | NULL, | |
8433c7e0 AM |
569 | &caller_profile, |
570 | SOF_NONE) != SWITCH_STATUS_SUCCESS) { | |
e028f269 MJ |
571 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error Creating Outgoing Channel! [%s]\n", dest); |
572 | goto failed; | |
573 | ||
574 | } | |
575 | ||
3d3ee88d | 576 | if (a_leg_session) a_leg_session->end_allow_threads(); |
d895c81d | 577 | channel = switch_core_session_get_channel(session); |
94b22258 | 578 | allocated = 1; |
ae76db7b AM |
579 | switch_channel_set_state(switch_core_session_get_channel(session), CS_TRANSMIT); |
580 | ||
e028f269 MJ |
581 | return SWITCH_STATUS_SUCCESS; |
582 | ||
583 | failed: | |
3d3ee88d | 584 | if (a_leg_session) a_leg_session->end_allow_threads(); |
e028f269 MJ |
585 | return SWITCH_STATUS_FALSE; |
586 | } | |
587 | ||
47985c56 | 588 | SWITCH_DECLARE(int) CoreSession::recordFile(char *file_name, int max_len, int silence_threshold, int silence_secs) |
bd2c91b0 MJ |
589 | { |
590 | switch_file_handle_t fh = { 0 }; | |
591 | switch_status_t status; | |
592 | ||
593 | fh.thresh = silence_threshold; | |
594 | fh.silence_hits = silence_secs; | |
595 | store_file_handle(&fh); | |
596 | begin_allow_threads(); | |
597 | status = switch_ivr_record_file(session, &fh, file_name, &args, max_len); | |
598 | end_allow_threads(); | |
599 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; | |
600 | ||
601 | } | |
e028f269 | 602 | |
47985c56 | 603 | SWITCH_DECLARE(int) CoreSession::flushEvents() |
6f78befa TL |
604 | { |
605 | switch_event_t *event; | |
606 | switch_channel_t *channel; | |
607 | ||
608 | if (!session) { | |
609 | return SWITCH_STATUS_FALSE; | |
610 | } | |
611 | channel = switch_core_session_get_channel(session); | |
6f78befa TL |
612 | |
613 | while (switch_core_session_dequeue_event(session, &event) == SWITCH_STATUS_SUCCESS) { | |
614 | switch_event_destroy(&event); | |
615 | } | |
616 | return SWITCH_STATUS_SUCCESS; | |
617 | } | |
618 | ||
47985c56 | 619 | SWITCH_DECLARE(int) CoreSession::flushDigits() |
6f78befa | 620 | { |
482badff | 621 | switch_channel_flush_dtmf(switch_core_session_get_channel(session)); |
6f78befa TL |
622 | return SWITCH_STATUS_SUCCESS; |
623 | } | |
624 | ||
47985c56 | 625 | SWITCH_DECLARE(int) CoreSession::setAutoHangup(bool val) |
6f78befa TL |
626 | { |
627 | if (!session) { | |
628 | return SWITCH_STATUS_FALSE; | |
629 | } | |
630 | if (val) { | |
631 | switch_set_flag(this, S_HUP); | |
632 | } else { | |
633 | switch_clear_flag(this, S_HUP); | |
634 | } | |
635 | return SWITCH_STATUS_SUCCESS; | |
636 | } | |
637 | ||
47985c56 | 638 | SWITCH_DECLARE(void) CoreSession::setCallerData(char *var, char *val) { |
e028f269 MJ |
639 | |
640 | if (strcmp(var, "dialplan") == 0) { | |
641 | caller_profile.dialplan = val; | |
642 | } | |
643 | if (strcmp(var, "context") == 0) { | |
644 | caller_profile.context = val; | |
645 | } | |
646 | if (strcmp(var, "caller_id_name") == 0) { | |
647 | caller_profile.caller_id_name = val; | |
648 | } | |
649 | if (strcmp(var, "caller_id_number") == 0) { | |
650 | caller_profile.caller_id_number = val; | |
651 | } | |
652 | if (strcmp(var, "network_addr") == 0) { | |
653 | caller_profile.network_addr = val; | |
654 | } | |
655 | if (strcmp(var, "ani") == 0) { | |
656 | caller_profile.ani = val; | |
657 | } | |
658 | if (strcmp(var, "aniii") == 0) { | |
659 | caller_profile.aniii = val; | |
660 | } | |
661 | if (strcmp(var, "rdnis") == 0) { | |
662 | caller_profile.rdnis = val; | |
663 | } | |
664 | if (strcmp(var, "username") == 0) { | |
665 | caller_profile.username = val; | |
666 | } | |
667 | ||
668 | } | |
669 | ||
47985c56 | 670 | SWITCH_DECLARE(void) CoreSession::setHangupHook(void *hangup_func) { |
6f78befa | 671 | |
a06997ee AM |
672 | sanity_check_noreturn; |
673 | ||
6f78befa TL |
674 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CoreSession::seHangupHook, hangup_func: %p\n", hangup_func); |
675 | on_hangup = hangup_func; | |
676 | switch_channel_t *channel = switch_core_session_get_channel(session); | |
6f78befa TL |
677 | |
678 | hook_state = switch_channel_get_state(channel); | |
679 | switch_channel_set_private(channel, "CoreSession", this); | |
680 | switch_core_event_hook_add_state_change(session, hanguphook); | |
fedefcb6 MJ |
681 | } |
682 | ||
f45d0601 MJ |
683 | /** \brief Store a file handle in the callback args |
684 | * | |
685 | * In a few of the methods like playFile and streamfile, | |
686 | * an empty switch_file_handle_t is created and passed | |
687 | * to core, and stored in callback args so that the callback | |
688 | * handler can retrieve it for pausing, ff, rewinding file ptr. | |
689 | * | |
690 | * \param fh - a switch_file_handle_t | |
691 | */ | |
692 | void CoreSession::store_file_handle(switch_file_handle_t *fh) { | |
693 | cb_state.extra = fh; // set a file handle so callback handler can pause | |
694 | args.buf = &cb_state; | |
695 | ap = &args; | |
696 | } | |
fedefcb6 | 697 | |
83f84876 | 698 | |
e028f269 MJ |
699 | /* ---- methods not bound to CoreSession instance ---- */ |
700 | ||
701 | ||
47985c56 | 702 | SWITCH_DECLARE(void) console_log(char *level_str, char *msg) |
e028f269 MJ |
703 | { |
704 | switch_log_level_t level = SWITCH_LOG_DEBUG; | |
705 | if (level_str) { | |
706 | level = switch_log_str2level(level_str); | |
cc71ce69 MJ |
707 | if (level == SWITCH_LOG_INVALID) { |
708 | level = SWITCH_LOG_DEBUG; | |
709 | } | |
e028f269 | 710 | } |
ae76db7b | 711 | switch_log_printf(SWITCH_CHANNEL_LOG, level, "%s", switch_str_nil(msg)); |
e028f269 MJ |
712 | } |
713 | ||
47985c56 | 714 | SWITCH_DECLARE(void) console_clean_log(char *msg) |
e028f269 | 715 | { |
ae76db7b | 716 | switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN,SWITCH_LOG_DEBUG, "%s", switch_str_nil(msg)); |
e028f269 MJ |
717 | } |
718 | ||
719 | ||
47985c56 | 720 | SWITCH_DECLARE(char *)api_execute(char *cmd, char *arg) |
e028f269 MJ |
721 | { |
722 | switch_stream_handle_t stream = { 0 }; | |
723 | SWITCH_STANDARD_STREAM(stream); | |
724 | switch_api_execute(cmd, arg, NULL, &stream); | |
725 | return (char *) stream.data; | |
726 | } | |
727 | ||
47985c56 | 728 | SWITCH_DECLARE(void) api_reply_delete(char *reply) |
e028f269 MJ |
729 | { |
730 | if (!switch_strlen_zero(reply)) { | |
731 | free(reply); | |
732 | } | |
733 | } | |
734 | ||
735 | ||
47985c56 | 736 | SWITCH_DECLARE(void) bridge(CoreSession &session_a, CoreSession &session_b) |
e028f269 MJ |
737 | { |
738 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "bridge called, session_a uuid: %s\n", session_a.get_uuid()); | |
739 | switch_input_callback_function_t dtmf_func = NULL; | |
740 | switch_input_args_t args; | |
741 | ||
742 | session_a.begin_allow_threads(); | |
743 | args = session_a.get_cb_args(); // get the cb_args data structure for session a | |
744 | dtmf_func = args.input_callback; // get the call back function | |
745 | switch_ivr_multi_threaded_bridge(session_a.session, session_b.session, dtmf_func, args.buf, args.buf); | |
746 | session_a.end_allow_threads(); | |
747 | ||
748 | } | |
749 | ||
750 | ||
47985c56 | 751 | SWITCH_DECLARE_NONSTD(switch_status_t) hanguphook(switch_core_session_t *session_hungup) |
6f78befa | 752 | { |
482badff | 753 | switch_channel_t *channel = switch_core_session_get_channel(session_hungup); |
6f78befa | 754 | CoreSession *coresession = NULL; |
482badff | 755 | switch_channel_state_t state = switch_channel_get_state(channel); |
6f78befa TL |
756 | |
757 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "hangup_hook called\n"); | |
59526679 | 758 | |
6f78befa | 759 | |
6f78befa TL |
760 | if ((coresession = (CoreSession *) switch_channel_get_private(channel, "CoreSession"))) { |
761 | if (coresession->hook_state != state) { | |
762 | coresession->hook_state = state; | |
763 | coresession->check_hangup_hook(); | |
764 | } | |
765 | } | |
766 | ||
767 | return SWITCH_STATUS_SUCCESS; | |
768 | } | |
769 | ||
770 | ||
47985c56 | 771 | SWITCH_DECLARE_NONSTD(switch_status_t) dtmf_callback(switch_core_session_t *session_cb, |
6f78befa TL |
772 | void *input, |
773 | switch_input_type_t itype, | |
774 | void *buf, | |
775 | unsigned int buflen) { | |
776 | ||
482badff | 777 | switch_channel_t *channel = switch_core_session_get_channel(session_cb); |
6f78befa TL |
778 | CoreSession *coresession = NULL; |
779 | switch_status_t result; | |
780 | ||
c806a20d | 781 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "dtmf_callback called\n"); |
6f78befa | 782 | |
59526679 AM |
783 | |
784 | //coresession = (CoreSession *) buf; | |
6f78befa | 785 | coresession = (CoreSession *) switch_channel_get_private(channel, "CoreSession"); |
59526679 | 786 | |
6f78befa TL |
787 | if (!coresession) { |
788 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid CoreSession\n"); | |
789 | return SWITCH_STATUS_FALSE; | |
790 | } | |
791 | ||
792 | result = coresession->run_dtmf_callback(input, itype); | |
793 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "process_callback_result returned\n"); | |
794 | if (result) { | |
795 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "process_callback_result returned: %d\n", result); | |
796 | } | |
797 | return result; | |
798 | ||
799 | } | |
800 | ||
59526679 AM |
801 | |
802 | ||
47985c56 | 803 | SWITCH_DECLARE(switch_status_t) CoreSession::process_callback_result(char *ret) |
e028f269 MJ |
804 | { |
805 | ||
806 | switch_file_handle_t *fh = NULL; | |
6f78befa | 807 | |
59526679 AM |
808 | if (fhp) { |
809 | fh = fhp; | |
810 | } else { | |
811 | if (!cb_state.extra) { | |
812 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Process callback result aborted because cb_state.extra is null\n"); | |
813 | return SWITCH_STATUS_FALSE; | |
814 | } | |
815 | ||
816 | fh = (switch_file_handle_t *) cb_state.extra; | |
817 | } | |
6f78befa | 818 | |
e028f269 MJ |
819 | |
820 | if (!fh) { | |
6f78befa TL |
821 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Process callback result aborted because fh is null\n"); |
822 | return SWITCH_STATUS_FALSE; | |
823 | } | |
824 | ||
825 | if (!fh->file_interface) { | |
826 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Process callback result aborted because fh->file_interface is null\n"); | |
e028f269 MJ |
827 | return SWITCH_STATUS_FALSE; |
828 | } | |
829 | ||
830 | if (!ret) { | |
59526679 | 831 | return SWITCH_STATUS_SUCCESS; |
6f78befa TL |
832 | } |
833 | ||
834 | if (!session) { | |
835 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Process callback result aborted because session is null\n"); | |
e028f269 MJ |
836 | return SWITCH_STATUS_FALSE; |
837 | } | |
838 | ||
6f78befa | 839 | |
e028f269 MJ |
840 | if (!strncasecmp(ret, "speed", 4)) { |
841 | char *p; | |
842 | ||
843 | if ((p = strchr(ret, ':'))) { | |
844 | p++; | |
845 | if (*p == '+' || *p == '-') { | |
846 | int step; | |
847 | if (!(step = atoi(p))) { | |
848 | step = 1; | |
849 | } | |
850 | fh->speed += step; | |
851 | } else { | |
852 | int speed = atoi(p); | |
853 | fh->speed = speed; | |
854 | } | |
855 | return SWITCH_STATUS_SUCCESS; | |
856 | } | |
857 | ||
858 | return SWITCH_STATUS_FALSE; | |
859 | ||
860 | } else if (!strcasecmp(ret, "pause")) { | |
861 | if (switch_test_flag(fh, SWITCH_FILE_PAUSE)) { | |
862 | switch_clear_flag(fh, SWITCH_FILE_PAUSE); | |
863 | } else { | |
864 | switch_set_flag(fh, SWITCH_FILE_PAUSE); | |
865 | } | |
866 | return SWITCH_STATUS_SUCCESS; | |
867 | } else if (!strcasecmp(ret, "stop")) { | |
868 | return SWITCH_STATUS_FALSE; | |
869 | } else if (!strcasecmp(ret, "restart")) { | |
870 | unsigned int pos = 0; | |
871 | fh->speed = 0; | |
872 | switch_core_file_seek(fh, &pos, 0, SEEK_SET); | |
873 | return SWITCH_STATUS_SUCCESS; | |
874 | } else if (!strncasecmp(ret, "seek", 4)) { | |
875 | switch_codec_t *codec; | |
876 | unsigned int samps = 0; | |
877 | unsigned int pos = 0; | |
878 | char *p; | |
879 | codec = switch_core_session_get_read_codec(session); | |
6f78befa | 880 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got codec\n"); |
e028f269 MJ |
881 | if ((p = strchr(ret, ':'))) { |
882 | p++; | |
883 | if (*p == '+' || *p == '-') { | |
884 | int step; | |
885 | if (!(step = atoi(p))) { | |
886 | step = 1000; | |
887 | } | |
888 | if (step > 0) { | |
889 | samps = step * (codec->implementation->samples_per_second / 1000); | |
6f78befa | 890 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "going to seek\n"); |
e028f269 | 891 | switch_core_file_seek(fh, &pos, samps, SEEK_CUR); |
6f78befa | 892 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "done seek\n"); |
e028f269 MJ |
893 | } else { |
894 | samps = step * (codec->implementation->samples_per_second / 1000); | |
6f78befa | 895 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "going to seek\n"); |
e028f269 | 896 | switch_core_file_seek(fh, &pos, fh->pos - samps, SEEK_SET); |
6f78befa | 897 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "done seek\n"); |
e028f269 MJ |
898 | } |
899 | } else { | |
900 | samps = atoi(p) * (codec->implementation->samples_per_second / 1000); | |
6f78befa | 901 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "going to seek\n"); |
e028f269 | 902 | switch_core_file_seek(fh, &pos, samps, SEEK_SET); |
6f78befa | 903 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "done seek\n"); |
e028f269 MJ |
904 | } |
905 | } | |
906 | ||
907 | return SWITCH_STATUS_SUCCESS; | |
908 | } | |
909 | ||
910 | if (!strcmp(ret, "true") || !strcmp(ret, "undefined")) { | |
6f78befa | 911 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "return success\n"); |
e028f269 MJ |
912 | return SWITCH_STATUS_SUCCESS; |
913 | } | |
914 | ||
6f78befa | 915 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "no match, return false\n"); |
e028f269 | 916 | |
c815c059 | 917 | return SWITCH_STATUS_FALSE; |
e028f269 MJ |
918 | } |
919 | ||
83f84876 AM |
920 | /* For Emacs: |
921 | * Local Variables: | |
922 | * mode:c | |
923 | * indent-tabs-mode:t | |
924 | * tab-width:4 | |
925 | * c-basic-offset:4 | |
926 | * End: | |
927 | * For VIM: | |
928 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab: | |
929 | */ |