]>
Commit | Line | Data |
---|---|---|
03845667 MJ |
1 | /* |
2 | * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application | |
babb2f83 | 3 | * Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org> |
03845667 MJ |
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 | |
ae220d33 | 20 | * Anthony Minessale II <anthm@freeswitch.org> |
03845667 MJ |
21 | * Portions created by the Initial Developer are Copyright (C) |
22 | * the Initial Developer. All Rights Reserved. | |
23 | * | |
24 | * Contributor(s): | |
25 | * | |
ae220d33 | 26 | * Anthony Minessale II <anthm@freeswitch.org> |
03845667 MJ |
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 | ||
eec83be1 AM |
40 | static void event_handler(switch_event_t *event) |
41 | { | |
a1cf7067 AM |
42 | EventConsumer *E = (EventConsumer *) event->bind_user_data; |
43 | switch_event_t *dup; | |
44 | ||
45 | switch_event_dup(&dup, event); | |
46 | ||
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 | } | |
50 | ||
eec83be1 AM |
51 | } |
52 | ||
a1cf7067 | 53 | SWITCH_DECLARE_CONSTRUCTOR EventConsumer::EventConsumer(const char *event_name, const char *subclass_name) |
eec83be1 | 54 | { |
a1cf7067 AM |
55 | switch_name_event(event_name, &e_event_id); |
56 | switch_core_new_memory_pool(&pool); | |
57 | ||
df7637f6 | 58 | if (!zstr(subclass_name)) { |
a1cf7067 | 59 | e_subclass_name = switch_core_strdup(pool, subclass_name); |
eec83be1 | 60 | } else { |
a1cf7067 | 61 | e_subclass_name = NULL; |
eec83be1 AM |
62 | } |
63 | ||
a1cf7067 AM |
64 | switch_queue_create(&events, 5000, pool); |
65 | ||
66 | if (switch_event_bind_removable(__FILE__, e_event_id, e_subclass_name, event_handler, this, &node) == SWITCH_STATUS_SUCCESS) { | |
67 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "bound to %s %s\n", event_name, switch_str_nil(e_subclass_name)); | |
68 | } else { | |
69 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot bind to %s %s\n", event_name, switch_str_nil(e_subclass_name)); | |
eec83be1 AM |
70 | } |
71 | ||
a1cf7067 AM |
72 | } |
73 | ||
eec83be1 | 74 | |
a1cf7067 AM |
75 | SWITCH_DECLARE(Event *) EventConsumer::pop(int block) |
76 | { | |
77 | void *pop = NULL; | |
78 | Event *ret = NULL; | |
79 | switch_event_t *event; | |
eec83be1 | 80 | |
a1cf7067 AM |
81 | if (block) { |
82 | switch_queue_pop(events, &pop); | |
83 | } else { | |
84 | switch_queue_trypop(events, &pop); | |
85 | } | |
86 | ||
87 | if ((event = (switch_event_t *) pop)) { | |
cf22bd97 | 88 | ret = new Event(event, 1); |
a1cf7067 | 89 | } |
eec83be1 | 90 | |
a1cf7067 AM |
91 | return ret; |
92 | } | |
eec83be1 AM |
93 | |
94 | SWITCH_DECLARE_CONSTRUCTOR EventConsumer::~EventConsumer() | |
95 | { | |
eec83be1 AM |
96 | if (node) { |
97 | switch_event_unbind(&node); | |
98 | } | |
a1cf7067 | 99 | |
608ca822 AM |
100 | if (events) { |
101 | switch_queue_interrupt_all(events); | |
102 | } | |
103 | ||
a1cf7067 | 104 | switch_core_destroy_memory_pool(&pool); |
eec83be1 | 105 | } |
aa47e3e5 AM |
106 | |
107 | SWITCH_DECLARE_CONSTRUCTOR IVRMenu::IVRMenu(IVRMenu *main, | |
108 | const char *name, | |
109 | const char *greeting_sound, | |
110 | const char *short_greeting_sound, | |
111 | const char *invalid_sound, | |
112 | const char *exit_sound, | |
113 | const char *confirm_macro, | |
114 | const char *confirm_key, | |
85c26566 BW |
115 | const char *tts_engine, |
116 | const char *tts_voice, | |
aa47e3e5 AM |
117 | int confirm_attempts, |
118 | int inter_timeout, | |
119 | int digit_len, | |
120 | int timeout, | |
fb06cc2d AM |
121 | int max_failures, |
122 | int max_timeouts) | |
aa47e3e5 AM |
123 | { |
124 | menu = NULL; | |
125 | switch_core_new_memory_pool(&pool); | |
126 | switch_assert(pool); | |
df7637f6 | 127 | if (zstr(name)) { |
aa47e3e5 AM |
128 | name = "no name"; |
129 | } | |
130 | ||
131 | switch_ivr_menu_init(&menu, main ? main->menu : NULL, name, greeting_sound, short_greeting_sound, invalid_sound, | |
85c26566 BW |
132 | exit_sound, confirm_macro, confirm_key, tts_engine, tts_voice, confirm_attempts, inter_timeout, |
133 | digit_len, timeout, max_failures, max_timeouts, pool); | |
aa47e3e5 AM |
134 | |
135 | ||
136 | } | |
137 | ||
138 | SWITCH_DECLARE_CONSTRUCTOR IVRMenu::~IVRMenu() | |
139 | { | |
140 | if (menu) { | |
141 | switch_ivr_menu_stack_free(menu); | |
142 | } | |
143 | switch_core_destroy_memory_pool(&pool); | |
144 | } | |
145 | ||
146 | SWITCH_DECLARE(void) IVRMenu::bindAction(char *action, const char *arg, const char *bind) | |
147 | { | |
148 | switch_ivr_action_t ivr_action = SWITCH_IVR_ACTION_NOOP; | |
149 | ||
878bbceb AM |
150 | this_check_void(); |
151 | ||
aa47e3e5 AM |
152 | if (switch_ivr_menu_str2action(action, &ivr_action) == SWITCH_STATUS_SUCCESS) { |
153 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "bind %s to %s(%s)\n", bind, action, arg); | |
154 | switch_ivr_menu_bind_action(menu, ivr_action, arg, bind); | |
155 | } else { | |
156 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid action %s\n", action); | |
157 | } | |
158 | } | |
159 | ||
160 | SWITCH_DECLARE(void) IVRMenu::execute(CoreSession *session, const char *name) | |
161 | { | |
878bbceb | 162 | this_check_void(); |
aa47e3e5 AM |
163 | switch_ivr_menu_execute(session->session, menu, (char *)name, NULL); |
164 | } | |
165 | ||
8f5a873d AM |
166 | SWITCH_DECLARE_CONSTRUCTOR API::API() |
167 | { | |
168 | last_data = NULL; | |
169 | } | |
170 | ||
171 | SWITCH_DECLARE_CONSTRUCTOR API::~API() | |
172 | { | |
173 | switch_safe_free(last_data); | |
174 | } | |
175 | ||
176 | ||
1a2131de | 177 | SWITCH_DECLARE(const char *) API::execute(const char *cmd, const char *arg) |
8f5a873d AM |
178 | { |
179 | switch_stream_handle_t stream = { 0 }; | |
878bbceb | 180 | this_check(""); |
8f5a873d AM |
181 | SWITCH_STANDARD_STREAM(stream); |
182 | switch_api_execute(cmd, arg, NULL, &stream); | |
41e7977c | 183 | switch_safe_free(last_data); |
8f5a873d AM |
184 | last_data = (char *) stream.data; |
185 | return last_data; | |
186 | } | |
187 | ||
072ec6a7 AM |
188 | |
189 | /* we have to do this as a string because swig and languages can't find an embedded way to pass a big int */ | |
8812477e | 190 | SWITCH_DECLARE(char *) API::getTime(void) |
072ec6a7 AM |
191 | { |
192 | switch_time_t now = switch_micro_time_now() / 1000; | |
193 | snprintf(time_buf, sizeof(time_buf), "%" SWITCH_TIME_T_FMT, now); | |
194 | return time_buf; | |
195 | } | |
196 | ||
197 | ||
198 | ||
1a2131de | 199 | SWITCH_DECLARE(const char *) API::executeString(const char *cmd) |
8f5a873d AM |
200 | { |
201 | char *arg; | |
202 | switch_stream_handle_t stream = { 0 }; | |
203 | char *mycmd = strdup(cmd); | |
204 | ||
205 | switch_assert(mycmd); | |
206 | ||
878bbceb AM |
207 | this_check(""); |
208 | ||
8f5a873d AM |
209 | if ((arg = strchr(mycmd, ' '))) { |
210 | *arg++ = '\0'; | |
211 | } | |
212 | ||
213 | switch_safe_free(last_data); | |
214 | ||
215 | SWITCH_STANDARD_STREAM(stream); | |
216 | switch_api_execute(mycmd, arg, NULL, &stream); | |
217 | last_data = (char *) stream.data; | |
218 | switch_safe_free(mycmd); | |
219 | return last_data; | |
220 | } | |
e028f269 | 221 | |
069d4681 | 222 | SWITCH_DECLARE_CONSTRUCTOR Event::Event(const char *type, const char *subclass_name) |
ae76db7b AM |
223 | { |
224 | switch_event_types_t event_id; | |
59526679 | 225 | |
ae76db7b AM |
226 | if (switch_name_event(type, &event_id) != SWITCH_STATUS_SUCCESS) { |
227 | event_id = SWITCH_EVENT_MESSAGE; | |
228 | } | |
229 | ||
df7637f6 | 230 | if (!zstr(subclass_name) && event_id != SWITCH_EVENT_CUSTOM) { |
7aa7dd7e BW |
231 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_WARNING, "Changing event type to custom because you specified a subclass name!\n"); |
232 | event_id = SWITCH_EVENT_CUSTOM; | |
233 | } | |
234 | ||
235 | if (switch_event_create_subclass(&event, event_id, subclass_name) != SWITCH_STATUS_SUCCESS) { | |
236 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Failed to create event!\n"); | |
237 | event = NULL; | |
238 | } | |
239 | ||
59526679 AM |
240 | serialized_string = NULL; |
241 | mine = 1; | |
242 | } | |
243 | ||
069d4681 | 244 | SWITCH_DECLARE_CONSTRUCTOR Event::Event(switch_event_t *wrap_me, int free_me) |
59526679 AM |
245 | { |
246 | event = wrap_me; | |
247 | mine = free_me; | |
248 | serialized_string = NULL; | |
ae76db7b AM |
249 | } |
250 | ||
069d4681 | 251 | SWITCH_DECLARE_CONSTRUCTOR Event::~Event() |
ae76db7b | 252 | { |
59526679 AM |
253 | |
254 | if (serialized_string) { | |
255 | free(serialized_string); | |
256 | } | |
257 | ||
258 | if (event && mine) { | |
ae76db7b AM |
259 | switch_event_destroy(&event); |
260 | } | |
261 | } | |
262 | ||
59526679 | 263 | |
069d4681 | 264 | SWITCH_DECLARE(const char *)Event::serialize(const char *format) |
59526679 AM |
265 | { |
266 | int isxml = 0; | |
267 | ||
878bbceb AM |
268 | this_check(""); |
269 | ||
59526679 | 270 | |
a1cf7067 AM |
271 | switch_safe_free(serialized_string); |
272 | ||
59526679 AM |
273 | if (!event) { |
274 | return ""; | |
275 | } | |
276 | ||
277 | if (format && !strcasecmp(format, "xml")) { | |
278 | isxml++; | |
279 | } | |
280 | ||
281 | if (isxml) { | |
282 | switch_xml_t xml; | |
59526679 AM |
283 | if ((xml = switch_event_xmlize(event, SWITCH_VA_NONE))) { |
284 | serialized_string = switch_xml_toxml(xml, SWITCH_FALSE); | |
285 | switch_xml_free(xml); | |
286 | return serialized_string; | |
287 | } else { | |
288 | return ""; | |
289 | } | |
290 | } else { | |
291 | if (switch_event_serialize(event, &serialized_string, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { | |
e858a1d8 AM |
292 | char *new_serialized_string = switch_mprintf("'%s'", serialized_string); |
293 | free(serialized_string); | |
294 | serialized_string = new_serialized_string; | |
59526679 AM |
295 | return serialized_string; |
296 | } | |
297 | } | |
298 | ||
299 | return ""; | |
300 | ||
301 | } | |
302 | ||
069d4681 | 303 | SWITCH_DECLARE(bool) Event::fire(void) |
ae76db7b | 304 | { |
878bbceb AM |
305 | |
306 | this_check(false); | |
307 | ||
59526679 AM |
308 | if (!mine) { |
309 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Not My event!\n"); | |
310 | return false; | |
311 | } | |
312 | ||
ae76db7b | 313 | if (event) { |
2b5f3563 AM |
314 | switch_event_t *new_event; |
315 | if (switch_event_dup(&new_event, event) == SWITCH_STATUS_SUCCESS) { | |
7aa7dd7e BW |
316 | if (switch_event_fire(&new_event) != SWITCH_STATUS_SUCCESS) { |
317 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Failed to fire the event!\n"); | |
318 | switch_event_destroy(&new_event); | |
319 | return false; | |
320 | } | |
2b5f3563 | 321 | return true; |
7aa7dd7e BW |
322 | } else { |
323 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Failed to dup the event!\n"); | |
2b5f3563 | 324 | } |
7aa7dd7e BW |
325 | } else { |
326 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to fire an event that does not exist!\n"); | |
ae76db7b AM |
327 | } |
328 | return false; | |
329 | } | |
330 | ||
b6d649fc | 331 | SWITCH_DECLARE(bool) Event::setPriority(switch_priority_t priority) |
ae76db7b | 332 | { |
878bbceb AM |
333 | this_check(false); |
334 | ||
ae76db7b AM |
335 | if (event) { |
336 | switch_event_set_priority(event, priority); | |
337 | return true; | |
7aa7dd7e BW |
338 | } else { |
339 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to setPriority an event that does not exist!\n"); | |
ae76db7b AM |
340 | } |
341 | return false; | |
342 | } | |
343 | ||
1a2131de | 344 | SWITCH_DECLARE(const char *)Event::getHeader(char *header_name) |
ae76db7b | 345 | { |
878bbceb AM |
346 | this_check(""); |
347 | ||
ae76db7b AM |
348 | if (event) { |
349 | return switch_event_get_header(event, header_name); | |
7aa7dd7e BW |
350 | } else { |
351 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to getHeader an event that does not exist!\n"); | |
ae76db7b AM |
352 | } |
353 | return NULL; | |
354 | } | |
355 | ||
b6d649fc | 356 | SWITCH_DECLARE(bool) Event::addHeader(const char *header_name, const char *value) |
ae76db7b | 357 | { |
878bbceb AM |
358 | this_check(false); |
359 | ||
ae76db7b AM |
360 | if (event) { |
361 | return switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header_name, value) == SWITCH_STATUS_SUCCESS ? true : false; | |
7aa7dd7e BW |
362 | } else { |
363 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to addHeader an event that does not exist!\n"); | |
ae76db7b AM |
364 | } |
365 | ||
366 | return false; | |
367 | } | |
368 | ||
b6d649fc | 369 | SWITCH_DECLARE(bool) Event::delHeader(const char *header_name) |
ae76db7b | 370 | { |
878bbceb AM |
371 | this_check(false); |
372 | ||
ae76db7b AM |
373 | if (event) { |
374 | return switch_event_del_header(event, header_name) == SWITCH_STATUS_SUCCESS ? true : false; | |
7aa7dd7e BW |
375 | } else { |
376 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to delHeader an event that does not exist!\n"); | |
ae76db7b AM |
377 | } |
378 | ||
379 | return false; | |
380 | } | |
381 | ||
382 | ||
b6d649fc | 383 | SWITCH_DECLARE(bool) Event::addBody(const char *value) |
ae76db7b | 384 | { |
878bbceb AM |
385 | this_check(false); |
386 | ||
ae76db7b AM |
387 | if (event) { |
388 | return switch_event_add_body(event, "%s", value) == SWITCH_STATUS_SUCCESS ? true : false; | |
7aa7dd7e BW |
389 | } else { |
390 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to addBody an event that does not exist!\n"); | |
ae76db7b AM |
391 | } |
392 | ||
393 | return false; | |
394 | } | |
395 | ||
b6d649fc | 396 | SWITCH_DECLARE(char *)Event::getBody(void) |
ae76db7b | 397 | { |
878bbceb AM |
398 | |
399 | this_check((char *)""); | |
400 | ||
ae76db7b AM |
401 | if (event) { |
402 | return switch_event_get_body(event); | |
7aa7dd7e BW |
403 | } else { |
404 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to getBody an event that does not exist!\n"); | |
ae76db7b AM |
405 | } |
406 | ||
407 | return NULL; | |
408 | } | |
409 | ||
d5e4046d | 410 | SWITCH_DECLARE(const char *)Event::getType(void) |
b6d649fc | 411 | { |
878bbceb AM |
412 | this_check(""); |
413 | ||
b6d649fc AM |
414 | if (event) { |
415 | return switch_event_name(event->event_id); | |
7aa7dd7e BW |
416 | } else { |
417 | switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to getType an event that does not exist!\n"); | |
b6d649fc AM |
418 | } |
419 | ||
d5e4046d | 420 | return (char *) "invalid"; |
b6d649fc AM |
421 | } |
422 | ||
a3ccefa7 AM |
423 | |
424 | SWITCH_DECLARE_CONSTRUCTOR DTMF::DTMF(char idigit, uint32_t iduration) | |
425 | { | |
426 | digit = idigit; | |
427 | ||
428 | if (iduration == 0) { | |
a358cf8e | 429 | iduration = SWITCH_DEFAULT_DTMF_DURATION; |
a3ccefa7 AM |
430 | } |
431 | ||
432 | duration = iduration; | |
433 | } | |
434 | ||
435 | SWITCH_DECLARE_CONSTRUCTOR DTMF::~DTMF() | |
436 | { | |
437 | ||
438 | } | |
439 | ||
440 | ||
069d4681 | 441 | SWITCH_DECLARE_CONSTRUCTOR Stream::Stream() |
ae76db7b AM |
442 | { |
443 | SWITCH_STANDARD_STREAM(mystream); | |
444 | stream_p = &mystream; | |
445 | mine = 1; | |
446 | } | |
447 | ||
069d4681 | 448 | SWITCH_DECLARE_CONSTRUCTOR Stream::Stream(switch_stream_handle_t *sp) |
ae76db7b AM |
449 | { |
450 | stream_p = sp; | |
451 | mine = 0; | |
452 | } | |
453 | ||
454 | ||
069d4681 | 455 | SWITCH_DECLARE_CONSTRUCTOR Stream::~Stream() |
ae76db7b AM |
456 | { |
457 | if (mine) { | |
458 | switch_safe_free(mystream.data); | |
459 | } | |
460 | } | |
461 | ||
069d4681 | 462 | SWITCH_DECLARE(void) Stream::write(const char *data) |
ae76db7b | 463 | { |
878bbceb | 464 | this_check_void(); |
ae76db7b AM |
465 | stream_p->write_function(stream_p, "%s", data); |
466 | } | |
467 | ||
069d4681 | 468 | SWITCH_DECLARE(const char *)Stream::get_data() |
ae76db7b | 469 | { |
878bbceb AM |
470 | this_check(""); |
471 | ||
ae76db7b AM |
472 | return stream_p ? (const char *)stream_p->data : NULL; |
473 | } | |
e028f269 MJ |
474 | |
475 | ||
47985c56 | 476 | SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession() |
e028f269 | 477 | { |
24a27c6e | 478 | init_vars(); |
e028f269 | 479 | } |
83f84876 | 480 | |
df5afbca | 481 | SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession(char *nuuid, CoreSession *a_leg) |
83f84876 | 482 | { |
a06997ee | 483 | init_vars(); |
24a27c6e | 484 | |
59526679 | 485 | if (!strchr(nuuid, '/') && (session = switch_core_session_locate(nuuid))) { |
94b22258 | 486 | uuid = strdup(nuuid); |
d895c81d | 487 | channel = switch_core_session_get_channel(session); |
94b22258 | 488 | allocated = 1; |
ae76db7b | 489 | } else { |
2261b687 | 490 | cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; |
a579a283 AM |
491 | if (switch_ivr_originate(a_leg ? a_leg->session : NULL, &session, &cause, nuuid, 60, NULL, NULL, NULL, NULL, NULL, SOF_NONE) |
492 | == SWITCH_STATUS_SUCCESS) { | |
d895c81d | 493 | channel = switch_core_session_get_channel(session); |
ae76db7b AM |
494 | allocated = 1; |
495 | switch_set_flag(this, S_HUP); | |
496 | uuid = strdup(switch_core_session_get_uuid(session)); | |
4b929592 | 497 | switch_channel_set_state(switch_core_session_get_channel(session), CS_SOFT_EXECUTE); |
ae76db7b AM |
498 | } |
499 | } | |
83f84876 AM |
500 | } |
501 | ||
47985c56 | 502 | SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession(switch_core_session_t *new_session) |
83f84876 AM |
503 | { |
504 | init_vars(); | |
24a27c6e | 505 | |
6d1f4f6d MJ |
506 | if (new_session) { |
507 | session = new_session; | |
508 | channel = switch_core_session_get_channel(session); | |
509 | allocated = 1; | |
ce14c6c2 | 510 | switch_core_session_read_lock_hangup(session); |
11fc21f7 | 511 | uuid = strdup(switch_core_session_get_uuid(session)); |
6d1f4f6d | 512 | } |
83f84876 AM |
513 | } |
514 | ||
47985c56 | 515 | SWITCH_DECLARE_CONSTRUCTOR CoreSession::~CoreSession() |
83f84876 | 516 | { |
75dbe890 | 517 | this_check_void(); |
ddd1ae14 | 518 | destroy(); |
83f84876 AM |
519 | } |
520 | ||
a5e10ebc AM |
521 | SWITCH_DECLARE(char *) CoreSession::getXMLCDR() |
522 | { | |
523 | ||
524 | switch_xml_t cdr; | |
878bbceb AM |
525 | |
526 | this_check((char *)""); | |
d5e4046d | 527 | sanity_check((char *)""); |
a5e10ebc AM |
528 | |
529 | switch_safe_free(xml_cdr_text); | |
530 | ||
531 | if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) { | |
532 | xml_cdr_text = switch_xml_toxml(cdr, SWITCH_FALSE); | |
533 | switch_xml_free(cdr); | |
534 | } | |
535 | ||
536 | return (char *) (xml_cdr_text ? xml_cdr_text : ""); | |
537 | } | |
538 | ||
539 | SWITCH_DECLARE(void) CoreSession::setEventData(Event *e) | |
540 | { | |
878bbceb | 541 | this_check_void(); |
a5e10ebc AM |
542 | sanity_check_noreturn; |
543 | ||
544 | if (channel && e->event) { | |
545 | switch_channel_event_set_data(channel, e->event); | |
546 | } | |
547 | } | |
548 | ||
47985c56 | 549 | SWITCH_DECLARE(int) CoreSession::answer() |
83f84876 AM |
550 | { |
551 | switch_status_t status; | |
878bbceb | 552 | this_check(-1); |
83f84876 AM |
553 | sanity_check(-1); |
554 | status = switch_channel_answer(channel); | |
555 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; | |
556 | } | |
557 | ||
47985c56 | 558 | SWITCH_DECLARE(int) CoreSession::preAnswer() |
83f84876 AM |
559 | { |
560 | switch_status_t status; | |
878bbceb | 561 | this_check(-1); |
83f84876 | 562 | sanity_check(-1); |
8107c49a | 563 | status = switch_channel_pre_answer(channel); |
83f84876 AM |
564 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; |
565 | } | |
566 | ||
bf91ac16 | 567 | SWITCH_DECLARE(void) CoreSession::hangup(const char *cause) |
83f84876 | 568 | { |
878bbceb AM |
569 | this_check_void(); |
570 | sanity_check_noreturn; | |
c2d5f970 | 571 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CoreSession::hangup\n"); |
996cfa54 | 572 | this->begin_allow_threads(); |
83f84876 | 573 | switch_channel_hangup(channel, switch_channel_str2cause(cause)); |
996cfa54 | 574 | this->end_allow_threads(); |
83f84876 AM |
575 | } |
576 | ||
47985c56 | 577 | SWITCH_DECLARE(void) CoreSession::setPrivate(char *var, void *val) |
59526679 | 578 | { |
878bbceb | 579 | this_check_void(); |
59526679 AM |
580 | sanity_check_noreturn; |
581 | switch_channel_set_private(channel, var, val); | |
582 | } | |
583 | ||
47985c56 | 584 | SWITCH_DECLARE(void *)CoreSession::getPrivate(char *var) |
59526679 | 585 | { |
878bbceb | 586 | this_check(NULL); |
59526679 AM |
587 | sanity_check(NULL); |
588 | return switch_channel_get_private(channel, var); | |
589 | } | |
590 | ||
47985c56 | 591 | SWITCH_DECLARE(void) CoreSession::setVariable(char *var, char *val) |
83f84876 | 592 | { |
878bbceb | 593 | this_check_void(); |
f32f6f24 | 594 | sanity_check_noreturn; |
83f84876 AM |
595 | switch_channel_set_variable(channel, var, val); |
596 | } | |
597 | ||
47985c56 | 598 | SWITCH_DECLARE(const char *)CoreSession::getVariable(char *var) |
83f84876 | 599 | { |
878bbceb AM |
600 | this_check(""); |
601 | sanity_check(""); | |
343d77a4 | 602 | return switch_channel_get_variable(channel, var); |
83f84876 AM |
603 | } |
604 | ||
b32de058 | 605 | SWITCH_DECLARE(void) CoreSession::execute(const char *app, const char *data) |
83f84876 | 606 | { |
878bbceb | 607 | this_check_void(); |
f32f6f24 | 608 | sanity_check_noreturn; |
83f84876 | 609 | |
b32de058 AM |
610 | begin_allow_threads(); |
611 | switch_core_session_execute_application(session, app, data); | |
612 | end_allow_threads(); | |
83f84876 AM |
613 | } |
614 | ||
47985c56 | 615 | SWITCH_DECLARE(void) CoreSession::setDTMFCallback(void *cbfunc, char *funcargs) { |
6f78befa | 616 | |
878bbceb | 617 | this_check_void(); |
a06997ee AM |
618 | sanity_check_noreturn; |
619 | ||
6f78befa TL |
620 | cb_state.funcargs = funcargs; |
621 | cb_state.function = cbfunc; | |
622 | ||
623 | args.buf = &cb_state; | |
624 | args.buflen = sizeof(cb_state); // not sure what this is used for, copy mod_spidermonkey | |
625 | ||
626 | switch_channel_set_private(channel, "CoreSession", this); | |
627 | ||
628 | // we cannot set the actual callback to a python function, because | |
629 | // the callback is a function pointer with a specific signature. | |
630 | // so, set it to the following c function which will act as a proxy, | |
631 | // finding the python callback in the args callback args structure | |
632 | args.input_callback = dtmf_callback; | |
633 | ap = &args; | |
634 | ||
635 | ||
636 | } | |
f45d0601 | 637 | |
47985c56 | 638 | SWITCH_DECLARE(void) CoreSession::sendEvent(Event *sendME) |
59526679 | 639 | { |
878bbceb AM |
640 | this_check_void(); |
641 | sanity_check_noreturn; | |
642 | ||
2b5f3563 AM |
643 | if (sendME->event) { |
644 | switch_event_t *new_event; | |
645 | if (switch_event_dup(&new_event, sendME->event) == SWITCH_STATUS_SUCCESS) { | |
646 | switch_core_session_receive_event(session, &new_event); | |
647 | } | |
59526679 AM |
648 | } |
649 | } | |
650 | ||
47985c56 | 651 | SWITCH_DECLARE(int) CoreSession::speak(char *text) |
83f84876 AM |
652 | { |
653 | switch_status_t status; | |
83f84876 | 654 | |
878bbceb | 655 | this_check(-1); |
83f84876 | 656 | sanity_check(-1); |
6f78befa | 657 | |
f45d0601 | 658 | if (!tts_name) { |
c2d5f970 | 659 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No TTS engine specified\n"); |
f45d0601 MJ |
660 | return SWITCH_STATUS_FALSE; |
661 | } | |
662 | ||
663 | if (!voice_name) { | |
c2d5f970 | 664 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No TTS voice specified\n"); |
f45d0601 MJ |
665 | return SWITCH_STATUS_FALSE; |
666 | } | |
667 | ||
160edc55 | 668 | |
fedefcb6 | 669 | begin_allow_threads(); |
160edc55 | 670 | status = switch_ivr_speak_text(session, tts_name, voice_name, text, ap); |
fedefcb6 | 671 | end_allow_threads(); |
83f84876 AM |
672 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; |
673 | } | |
674 | ||
47985c56 | 675 | SWITCH_DECLARE(void) CoreSession::set_tts_parms(char *tts_name_p, char *voice_name_p) |
83f84876 | 676 | { |
878bbceb | 677 | this_check_void(); |
f32f6f24 | 678 | sanity_check_noreturn; |
83f84876 AM |
679 | switch_safe_free(tts_name); |
680 | switch_safe_free(voice_name); | |
681 | tts_name = strdup(tts_name_p); | |
682 | voice_name = strdup(voice_name_p); | |
683 | } | |
684 | ||
c806a20d TL |
685 | |
686 | ||
3bc20b3c BW |
687 | SWITCH_DECLARE(int) CoreSession::collectDigits(int abs_timeout) { |
688 | return collectDigits(0, abs_timeout); | |
689 | } | |
690 | ||
691 | SWITCH_DECLARE(int) CoreSession::collectDigits(int digit_timeout, int abs_timeout) { | |
878bbceb | 692 | this_check(-1); |
c806a20d TL |
693 | sanity_check(-1); |
694 | begin_allow_threads(); | |
3bc20b3c | 695 | switch_ivr_collect_digits_callback(session, ap, digit_timeout, abs_timeout); |
c806a20d | 696 | end_allow_threads(); |
a4301f0d | 697 | return SWITCH_STATUS_SUCCESS; |
c806a20d TL |
698 | } |
699 | ||
444c93c3 MJ |
700 | SWITCH_DECLARE(char *) CoreSession::getDigits(int maxdigits, char *terminators, int timeout) |
701 | { | |
702 | return getDigits(maxdigits, terminators, timeout, 0); | |
703 | } | |
704 | ||
38038078 | 705 | SWITCH_DECLARE(char *) CoreSession::getDigits(int maxdigits, |
4fda174f | 706 | char *terminators, |
444c93c3 MJ |
707 | int timeout, |
708 | int interdigit) | |
83f84876 AM |
709 | { |
710 | switch_status_t status; | |
878bbceb | 711 | this_check((char *)""); |
d5e4046d | 712 | sanity_check((char *)""); |
fedefcb6 | 713 | begin_allow_threads(); |
4fda174f | 714 | char terminator; |
6f78befa | 715 | |
85fc8c37 | 716 | memset(dtmf_buf, 0, sizeof(dtmf_buf)); |
f45d0601 MJ |
717 | status = switch_ivr_collect_digits_count(session, |
718 | dtmf_buf, | |
85fc8c37 | 719 | sizeof(dtmf_buf), |
e8f7c1b4 | 720 | maxdigits, |
f45d0601 | 721 | terminators, |
4fda174f | 722 | &terminator, |
444c93c3 | 723 | (uint32_t) timeout, (uint32_t)interdigit, 0); |
6f78befa | 724 | |
c2d5f970 | 725 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "getDigits dtmf_buf: %s\n", dtmf_buf); |
fedefcb6 | 726 | end_allow_threads(); |
85fc8c37 | 727 | return dtmf_buf; |
83f84876 AM |
728 | } |
729 | ||
47985c56 | 730 | SWITCH_DECLARE(int) CoreSession::transfer(char *extension, char *dialplan, char *context) |
83f84876 AM |
731 | { |
732 | switch_status_t status; | |
878bbceb | 733 | this_check(-1); |
83f84876 | 734 | sanity_check(-1); |
e028f269 | 735 | begin_allow_threads(); |
83f84876 | 736 | status = switch_ivr_session_transfer(session, extension, dialplan, context); |
c2d5f970 | 737 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "transfer result: %d\n", status); |
e028f269 | 738 | end_allow_threads(); |
83f84876 AM |
739 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; |
740 | } | |
741 | ||
8e0b64a1 AM |
742 | |
743 | SWITCH_DECLARE(char *) CoreSession::read(int min_digits, | |
744 | int max_digits, | |
745 | const char *prompt_audio_file, | |
746 | int timeout, | |
747 | const char *valid_terminators) | |
748 | { | |
878bbceb AM |
749 | this_check((char *)""); |
750 | sanity_check((char *)""); | |
8e0b64a1 AM |
751 | if (min_digits < 1) { |
752 | min_digits = 1; | |
753 | } | |
754 | ||
755 | if (max_digits < 1) { | |
756 | max_digits = 1; | |
757 | } | |
758 | ||
759 | if (timeout < 1) { | |
760 | timeout = 1; | |
761 | } | |
762 | ||
5195d311 | 763 | begin_allow_threads(); |
8e0b64a1 | 764 | switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, NULL, dtmf_buf, sizeof(dtmf_buf), timeout, valid_terminators); |
5195d311 AM |
765 | end_allow_threads(); |
766 | ||
8e0b64a1 AM |
767 | return dtmf_buf; |
768 | } | |
769 | ||
85fc8c37 | 770 | SWITCH_DECLARE(char *) CoreSession::playAndGetDigits(int min_digits, |
8b8a7f14 BW |
771 | int max_digits, |
772 | int max_tries, | |
773 | int timeout, | |
774 | char *terminators, | |
775 | char *audio_files, | |
69f73575 | 776 | char *bad_input_audio_files, |
dbb40708 BW |
777 | char *digits_regex, |
778 | const char *var_name) | |
83f84876 AM |
779 | { |
780 | switch_status_t status; | |
d5e4046d | 781 | sanity_check((char *)""); |
878bbceb | 782 | this_check((char *)""); |
fedefcb6 | 783 | begin_allow_threads(); |
85fc8c37 | 784 | memset(dtmf_buf, 0, sizeof(dtmf_buf)); |
fedefcb6 MJ |
785 | status = switch_play_and_get_digits( session, |
786 | (uint32_t) min_digits, | |
787 | (uint32_t) max_digits, | |
788 | (uint32_t) max_tries, | |
789 | (uint32_t) timeout, | |
790 | terminators, | |
791 | audio_files, | |
69f73575 BW |
792 | bad_input_audio_files, |
793 | var_name, | |
c806a20d | 794 | dtmf_buf, |
85fc8c37 | 795 | sizeof(dtmf_buf), |
fedefcb6 | 796 | digits_regex); |
6f78befa | 797 | |
fedefcb6 | 798 | end_allow_threads(); |
85fc8c37 | 799 | return dtmf_buf; |
83f84876 AM |
800 | } |
801 | ||
40efe06a AM |
802 | SWITCH_DECLARE(void) CoreSession::say(const char *tosay, const char *module_name, const char *say_type, const char *say_method) |
803 | { | |
878bbceb | 804 | this_check_void(); |
40efe06a AM |
805 | sanity_check_noreturn; |
806 | if (!(tosay && module_name && say_type && say_method)) { | |
c2d5f970 | 807 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! invalid args.\n"); |
40efe06a AM |
808 | return; |
809 | } | |
810 | begin_allow_threads(); | |
811 | switch_ivr_say(session, tosay, module_name, say_type, say_method, ap); | |
812 | end_allow_threads(); | |
813 | } | |
814 | ||
815 | SWITCH_DECLARE(void) CoreSession::sayPhrase(const char *phrase_name, const char *phrase_data, const char *phrase_lang) | |
816 | { | |
878bbceb | 817 | this_check_void(); |
40efe06a AM |
818 | sanity_check_noreturn; |
819 | ||
820 | if (!(phrase_name)) { | |
c2d5f970 | 821 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! invalid args.\n"); |
40efe06a AM |
822 | return; |
823 | } | |
824 | ||
825 | begin_allow_threads(); | |
826 | switch_ivr_phrase_macro(session, phrase_name, phrase_data, phrase_lang, ap); | |
827 | end_allow_threads(); | |
828 | } | |
829 | ||
47985c56 | 830 | SWITCH_DECLARE(int) CoreSession::streamFile(char *file, int starting_sample_count) { |
f45d0601 MJ |
831 | |
832 | switch_status_t status; | |
59526679 | 833 | //switch_file_handle_t fh = { 0 }; |
622a2733 | 834 | const char *prebuf; |
f2495ec8 | 835 | switch_file_handle_t local_fh; |
f45d0601 | 836 | |
878bbceb | 837 | this_check(-1); |
f45d0601 | 838 | sanity_check(-1); |
59526679 AM |
839 | |
840 | memset(&local_fh, 0, sizeof(local_fh)); | |
841 | fhp = &local_fh; | |
842 | local_fh.samples = starting_sample_count; | |
f45d0601 | 843 | |
f45d0601 MJ |
844 | |
845 | if ((prebuf = switch_channel_get_variable(this->channel, "stream_prebuffer"))) { | |
846 | int maybe = atoi(prebuf); | |
847 | if (maybe > 0) { | |
59526679 | 848 | local_fh.prebuf = maybe; |
f45d0601 MJ |
849 | } |
850 | } | |
851 | ||
59526679 AM |
852 | begin_allow_threads(); |
853 | status = switch_ivr_play_file(session, fhp, file, ap); | |
854 | end_allow_threads(); | |
855 | ||
a3ccefa7 AM |
856 | fhp = NULL; |
857 | ||
f45d0601 MJ |
858 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; |
859 | ||
860 | } | |
861 | ||
71054917 | 862 | SWITCH_DECLARE(int) CoreSession::sleep(int ms, int sync) { |
32bbdb74 AM |
863 | |
864 | switch_status_t status; | |
865 | ||
866 | this_check(-1); | |
867 | sanity_check(-1); | |
868 | ||
869 | begin_allow_threads(); | |
71054917 | 870 | status = switch_ivr_sleep(session, ms, (switch_bool_t) sync, ap); |
32bbdb74 AM |
871 | end_allow_threads(); |
872 | ||
873 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; | |
874 | ||
875 | } | |
876 | ||
47985c56 | 877 | SWITCH_DECLARE(bool) CoreSession::ready() { |
f45d0601 | 878 | |
878bbceb | 879 | this_check(false); |
83ebebc5 AM |
880 | |
881 | if (!session) { | |
882 | return false; | |
883 | } | |
884 | sanity_check(false); | |
885 | ||
482badff | 886 | return switch_channel_ready(channel) != 0; |
fedefcb6 MJ |
887 | } |
888 | ||
830a8493 AM |
889 | SWITCH_DECLARE(bool) CoreSession::mediaReady() { |
890 | ||
891 | this_check(false); | |
892 | sanity_check(false); | |
893 | return switch_channel_media_ready(channel) != 0; | |
894 | } | |
895 | ||
896 | SWITCH_DECLARE(bool) CoreSession::answered() { | |
897 | ||
898 | this_check(false); | |
899 | sanity_check(false); | |
900 | return switch_channel_test_flag(channel, CF_ANSWERED) != 0; | |
901 | } | |
902 | ||
ddd1ae14 AM |
903 | SWITCH_DECLARE(void) CoreSession::destroy(void) |
904 | { | |
905 | this_check_void(); | |
4025b424 AM |
906 | |
907 | if (!allocated) { | |
908 | return; | |
909 | } | |
ddd1ae14 AM |
910 | |
911 | switch_safe_free(xml_cdr_text); | |
912 | switch_safe_free(uuid); | |
913 | switch_safe_free(tts_name); | |
914 | switch_safe_free(voice_name); | |
915 | ||
916 | if (session) { | |
523e0653 AM |
917 | if (!channel) { |
918 | channel = switch_core_session_get_channel(session); | |
919 | } | |
920 | ||
921 | if (channel) { | |
922 | switch_channel_set_private(channel, "CoreSession", NULL); | |
923 | } | |
924 | ||
c2d5f970 | 925 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "destroy/unlink session from object\n"); |
4025b424 | 926 | |
523e0653 | 927 | if (switch_channel_up(channel) && switch_test_flag(this, S_HUP) && !switch_channel_test_flag(channel, CF_TRANSFER)) { |
ddd1ae14 AM |
928 | switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); |
929 | } | |
930 | switch_core_session_rwunlock(session); | |
931 | session = NULL; | |
523e0653 | 932 | channel = NULL; |
ddd1ae14 AM |
933 | } |
934 | ||
4025b424 | 935 | init_vars(); |
ddd1ae14 AM |
936 | |
937 | } | |
938 | ||
c54f0c39 AM |
939 | SWITCH_DECLARE(const char *) CoreSession::hangupCause() |
940 | { | |
2261b687 | 941 | this_check(NULL); |
c54f0c39 AM |
942 | return switch_channel_cause2str(cause); |
943 | } | |
944 | ||
635e2fb5 AM |
945 | SWITCH_DECLARE(const char *) CoreSession::getState() |
946 | { | |
947 | this_check(NULL); | |
948 | ||
949 | if (channel) { | |
950 | return switch_channel_state_name(switch_channel_get_state(channel)); | |
951 | } | |
952 | ||
953 | return "ERROR"; | |
954 | ||
955 | } | |
956 | ||
5a5f3081 | 957 | SWITCH_DECLARE(int) CoreSession::originate(CoreSession *a_leg_session, char *dest, int timeout, switch_state_handler_table_t *handlers) |
e028f269 MJ |
958 | { |
959 | ||
e028f269 | 960 | switch_core_session_t *aleg_core_session = NULL; |
e028f269 | 961 | |
878bbceb | 962 | this_check(0); |
878bbceb | 963 | |
e028f269 MJ |
964 | cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; |
965 | ||
700aa0df TL |
966 | if (a_leg_session != NULL) { |
967 | aleg_core_session = a_leg_session->session; | |
e028f269 MJ |
968 | } |
969 | ||
700aa0df TL |
970 | // this session has no valid switch_core_session_t at this point, and therefore |
971 | // no valid channel. since the threadstate is stored in the channel, and there | |
972 | // is none, if we try to call begin_alllow_threads it will fail miserably. | |
973 | // use the 'a leg session' to do the thread swapping stuff. | |
3d3ee88d | 974 | if (a_leg_session) a_leg_session->begin_allow_threads(); |
e028f269 | 975 | |
e028f269 MJ |
976 | if (switch_ivr_originate(aleg_core_session, |
977 | &session, | |
978 | &cause, | |
979 | dest, | |
980 | timeout, | |
5a5f3081 | 981 | handlers, |
e028f269 MJ |
982 | NULL, |
983 | NULL, | |
c5f1d9ec | 984 | NULL, |
a579a283 | 985 | NULL, |
8433c7e0 | 986 | SOF_NONE) != SWITCH_STATUS_SUCCESS) { |
e028f269 MJ |
987 | switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error Creating Outgoing Channel! [%s]\n", dest); |
988 | goto failed; | |
989 | ||
990 | } | |
991 | ||
3d3ee88d | 992 | if (a_leg_session) a_leg_session->end_allow_threads(); |
d895c81d | 993 | channel = switch_core_session_get_channel(session); |
94b22258 | 994 | allocated = 1; |
2a3be1dc MR |
995 | switch_safe_free(uuid); |
996 | uuid = strdup(switch_core_session_get_uuid(session)); | |
4b929592 | 997 | switch_channel_set_state(switch_core_session_get_channel(session), CS_SOFT_EXECUTE); |
ae76db7b | 998 | |
e028f269 MJ |
999 | return SWITCH_STATUS_SUCCESS; |
1000 | ||
1001 | failed: | |
3d3ee88d | 1002 | if (a_leg_session) a_leg_session->end_allow_threads(); |
e028f269 MJ |
1003 | return SWITCH_STATUS_FALSE; |
1004 | } | |
1005 | ||
3a67cbf4 | 1006 | SWITCH_DECLARE(int) CoreSession::recordFile(char *file_name, int time_limit, int silence_threshold, int silence_hits) |
bd2c91b0 | 1007 | { |
bd2c91b0 | 1008 | switch_status_t status; |
f2495ec8 | 1009 | switch_file_handle_t local_fh; |
bd2c91b0 | 1010 | |
878bbceb AM |
1011 | this_check(-1); |
1012 | sanity_check(-1); | |
1013 | ||
a3ccefa7 AM |
1014 | memset(&local_fh, 0, sizeof(local_fh)); |
1015 | fhp = &local_fh; | |
1016 | local_fh.thresh = silence_threshold; | |
3a67cbf4 | 1017 | local_fh.silence_hits = silence_hits; |
a3ccefa7 | 1018 | |
bd2c91b0 | 1019 | begin_allow_threads(); |
3a67cbf4 | 1020 | status = switch_ivr_record_file(session, &local_fh, file_name, &args, time_limit); |
bd2c91b0 | 1021 | end_allow_threads(); |
a3ccefa7 AM |
1022 | |
1023 | fhp = NULL; | |
1024 | ||
bd2c91b0 MJ |
1025 | return status == SWITCH_STATUS_SUCCESS ? 1 : 0; |
1026 | ||
1027 | } | |
e028f269 | 1028 | |
47985c56 | 1029 | SWITCH_DECLARE(int) CoreSession::flushEvents() |
6f78befa TL |
1030 | { |
1031 | switch_event_t *event; | |
1032 | switch_channel_t *channel; | |
1033 | ||
878bbceb AM |
1034 | this_check(-1); |
1035 | sanity_check(-1); | |
1036 | ||
6f78befa TL |
1037 | if (!session) { |
1038 | return SWITCH_STATUS_FALSE; | |
1039 | } | |
1040 | channel = switch_core_session_get_channel(session); | |
6f78befa | 1041 | |
99026e02 | 1042 | while (switch_core_session_dequeue_event(session, &event, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { |
6f78befa TL |
1043 | switch_event_destroy(&event); |
1044 | } | |
1045 | return SWITCH_STATUS_SUCCESS; | |
1046 | } | |
1047 | ||
47985c56 | 1048 | SWITCH_DECLARE(int) CoreSession::flushDigits() |
6f78befa | 1049 | { |
878bbceb AM |
1050 | this_check(-1); |
1051 | sanity_check(-1); | |
482badff | 1052 | switch_channel_flush_dtmf(switch_core_session_get_channel(session)); |
6f78befa TL |
1053 | return SWITCH_STATUS_SUCCESS; |
1054 | } | |
1055 | ||
47985c56 | 1056 | SWITCH_DECLARE(int) CoreSession::setAutoHangup(bool val) |
6f78befa | 1057 | { |
878bbceb AM |
1058 | this_check(-1); |
1059 | sanity_check(-1); | |
1060 | ||
6f78befa TL |
1061 | if (!session) { |
1062 | return SWITCH_STATUS_FALSE; | |
1063 | } | |
1064 | if (val) { | |
1065 | switch_set_flag(this, S_HUP); | |
1066 | } else { | |
1067 | switch_clear_flag(this, S_HUP); | |
1068 | } | |
1069 | return SWITCH_STATUS_SUCCESS; | |
1070 | } | |
1071 | ||
7f4c8a6d AM |
1072 | SWITCH_DECLARE(void) CoreSession::waitForAnswer(CoreSession *calling_session) |
1073 | { | |
1074 | this_check_void(); | |
1075 | sanity_check_noreturn; | |
1076 | ||
1077 | switch_ivr_wait_for_answer(calling_session ? calling_session->session : NULL, session); | |
1078 | ||
1079 | } | |
1080 | ||
47985c56 | 1081 | SWITCH_DECLARE(void) CoreSession::setHangupHook(void *hangup_func) { |
6f78befa | 1082 | |
878bbceb | 1083 | this_check_void(); |
a06997ee | 1084 | sanity_check_noreturn; |
878bbceb | 1085 | |
c2d5f970 | 1086 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CoreSession::seHangupHook, hangup_func: %p\n", hangup_func); |
6f78befa TL |
1087 | on_hangup = hangup_func; |
1088 | switch_channel_t *channel = switch_core_session_get_channel(session); | |
6f78befa TL |
1089 | |
1090 | hook_state = switch_channel_get_state(channel); | |
1091 | switch_channel_set_private(channel, "CoreSession", this); | |
1092 | switch_core_event_hook_add_state_change(session, hanguphook); | |
fedefcb6 MJ |
1093 | } |
1094 | ||
e028f269 MJ |
1095 | /* ---- methods not bound to CoreSession instance ---- */ |
1096 | ||
8f5a873d AM |
1097 | SWITCH_DECLARE(void) consoleLog(char *level_str, char *msg) |
1098 | { | |
1099 | return console_log(level_str, msg); | |
1100 | } | |
1101 | ||
1102 | SWITCH_DECLARE(void) consoleCleanLog(char *msg) | |
1103 | { | |
1104 | return console_clean_log(msg); | |
1105 | } | |
e028f269 | 1106 | |
47985c56 | 1107 | SWITCH_DECLARE(void) console_log(char *level_str, char *msg) |
e028f269 MJ |
1108 | { |
1109 | switch_log_level_t level = SWITCH_LOG_DEBUG; | |
1110 | if (level_str) { | |
1111 | level = switch_log_str2level(level_str); | |
cc71ce69 MJ |
1112 | if (level == SWITCH_LOG_INVALID) { |
1113 | level = SWITCH_LOG_DEBUG; | |
1114 | } | |
e028f269 | 1115 | } |
ae76db7b | 1116 | switch_log_printf(SWITCH_CHANNEL_LOG, level, "%s", switch_str_nil(msg)); |
e028f269 MJ |
1117 | } |
1118 | ||
47985c56 | 1119 | SWITCH_DECLARE(void) console_clean_log(char *msg) |
e028f269 | 1120 | { |
ae76db7b | 1121 | switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN,SWITCH_LOG_DEBUG, "%s", switch_str_nil(msg)); |
e028f269 MJ |
1122 | } |
1123 | ||
1124 | ||
6ea577d7 | 1125 | SWITCH_DECLARE(void) msleep(unsigned ms) |
369e6065 MJ |
1126 | { |
1127 | switch_sleep(ms * 1000); | |
1128 | return; | |
1129 | } | |
1130 | ||
47985c56 | 1131 | SWITCH_DECLARE(void) bridge(CoreSession &session_a, CoreSession &session_b) |
e028f269 | 1132 | { |
e028f269 MJ |
1133 | switch_input_callback_function_t dtmf_func = NULL; |
1134 | switch_input_args_t args; | |
920ef82c AM |
1135 | switch_channel_t *channel_a = NULL, *channel_b = NULL; |
1136 | const char *err = "Channels not ready\n"; | |
1137 | ||
1138 | if (session_a.allocated && session_a.session && session_b.allocated && session_b.session) { | |
1139 | channel_a = switch_core_session_get_channel(session_a.session); | |
1140 | channel_b = switch_core_session_get_channel(session_b.session); | |
1141 | ||
1142 | if (switch_channel_ready(channel_a) && switch_channel_ready(channel_b)) { | |
1143 | session_a.begin_allow_threads(); | |
ab9af349 | 1144 | if (!switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_media_ready(channel_a)) { |
88ae7890 | 1145 | switch_channel_pre_answer(channel_a); |
920ef82c | 1146 | } |
88ae7890 | 1147 | |
920ef82c AM |
1148 | if (switch_channel_ready(channel_a) && switch_channel_ready(channel_b)) { |
1149 | args = session_a.get_cb_args(); // get the cb_args data structure for session a | |
1150 | dtmf_func = args.input_callback; // get the call back function | |
1151 | err = NULL; | |
1152 | switch_ivr_multi_threaded_bridge(session_a.session, session_b.session, dtmf_func, args.buf, args.buf); | |
920ef82c | 1153 | } |
df5afbca | 1154 | session_a.end_allow_threads(); |
920ef82c AM |
1155 | } |
1156 | } | |
1157 | ||
1158 | if (err) { | |
c2d5f970 | 1159 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a.session), SWITCH_LOG_ERROR, "%s", err); |
920ef82c | 1160 | } |
e028f269 | 1161 | |
e028f269 MJ |
1162 | |
1163 | } | |
1164 | ||
47985c56 | 1165 | SWITCH_DECLARE_NONSTD(switch_status_t) hanguphook(switch_core_session_t *session_hungup) |
6f78befa | 1166 | { |
482badff | 1167 | switch_channel_t *channel = switch_core_session_get_channel(session_hungup); |
6f78befa | 1168 | CoreSession *coresession = NULL; |
482badff | 1169 | switch_channel_state_t state = switch_channel_get_state(channel); |
6f78befa | 1170 | |
6f78befa TL |
1171 | if ((coresession = (CoreSession *) switch_channel_get_private(channel, "CoreSession"))) { |
1172 | if (coresession->hook_state != state) { | |
1173 | coresession->hook_state = state; | |
1174 | coresession->check_hangup_hook(); | |
1175 | } | |
1176 | } | |
1177 | ||
1178 | return SWITCH_STATUS_SUCCESS; | |
1179 | } | |
1180 | ||
1181 | ||
47985c56 | 1182 | SWITCH_DECLARE_NONSTD(switch_status_t) dtmf_callback(switch_core_session_t *session_cb, |
8b8a7f14 BW |
1183 | void *input, |
1184 | switch_input_type_t itype, | |
1185 | void *buf, | |
1186 | unsigned int buflen) { | |
6f78befa | 1187 | |
482badff | 1188 | switch_channel_t *channel = switch_core_session_get_channel(session_cb); |
6f78befa | 1189 | CoreSession *coresession = NULL; |
6f78befa | 1190 | |
6f78befa | 1191 | coresession = (CoreSession *) switch_channel_get_private(channel, "CoreSession"); |
59526679 | 1192 | |
6f78befa | 1193 | if (!coresession) { |
6f78befa TL |
1194 | return SWITCH_STATUS_FALSE; |
1195 | } | |
1196 | ||
4780a3d3 | 1197 | return coresession->run_dtmf_callback(input, itype); |
6f78befa TL |
1198 | } |
1199 | ||
59526679 | 1200 | |
fe854bdb | 1201 | SWITCH_DECLARE(switch_status_t) CoreSession::process_callback_result(char *result) |
e028f269 MJ |
1202 | { |
1203 | ||
878bbceb AM |
1204 | this_check(SWITCH_STATUS_FALSE); |
1205 | sanity_check(SWITCH_STATUS_FALSE); | |
1206 | ||
df7637f6 | 1207 | if (zstr(result)) { |
be276e0c AM |
1208 | return SWITCH_STATUS_SUCCESS; |
1209 | } | |
1210 | ||
59526679 | 1211 | if (fhp) { |
ea88aed0 AM |
1212 | if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { |
1213 | return SWITCH_STATUS_FALSE; | |
1214 | } | |
1215 | ||
db5eb288 | 1216 | if (!strncasecmp(result, "speed", 5)) { |
8b8a7f14 BW |
1217 | char *p; |
1218 | ||
1219 | if ((p = strchr(result, ':'))) { | |
1220 | p++; | |
1221 | if (*p == '+' || *p == '-') { | |
1222 | int step; | |
1223 | if (!(step = atoi(p))) { | |
1224 | step = 1; | |
1225 | } | |
b47382df | 1226 | fhp->speed += step; |
8b8a7f14 BW |
1227 | } else { |
1228 | int speed = atoi(p); | |
b47382df | 1229 | fhp->speed = speed; |
8b8a7f14 BW |
1230 | } |
1231 | return SWITCH_STATUS_SUCCESS; | |
1232 | } | |
e028f269 | 1233 | |
8b8a7f14 | 1234 | return SWITCH_STATUS_FALSE; |
e028f269 | 1235 | |
6ffe5cc9 BW |
1236 | } else if (!strncasecmp(result, "volume", 6)) { |
1237 | char *p; | |
1238 | ||
1239 | if ((p = strchr(result, ':'))) { | |
1240 | p++; | |
1241 | if (*p == '+' || *p == '-') { | |
1242 | int step; | |
1243 | if (!(step = atoi(p))) { | |
1244 | step = 1; | |
1245 | } | |
1246 | fhp->vol += step; | |
1247 | } else { | |
1248 | int vol = atoi(p); | |
1249 | fhp->vol = vol; | |
1250 | } | |
1251 | return SWITCH_STATUS_SUCCESS; | |
1252 | } | |
1253 | ||
1254 | if (fhp->vol) { | |
1255 | switch_normalize_volume(fhp->vol); | |
1256 | } | |
1257 | ||
1258 | return SWITCH_STATUS_FALSE; | |
8b8a7f14 | 1259 | } else if (!strcasecmp(result, "pause")) { |
b47382df BW |
1260 | if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)) { |
1261 | switch_clear_flag(fhp, SWITCH_FILE_PAUSE); | |
e028f269 | 1262 | } else { |
b47382df | 1263 | switch_set_flag(fhp, SWITCH_FILE_PAUSE); |
e028f269 MJ |
1264 | } |
1265 | return SWITCH_STATUS_SUCCESS; | |
8b8a7f14 BW |
1266 | } else if (!strcasecmp(result, "stop")) { |
1267 | return SWITCH_STATUS_FALSE; | |
1268 | } else if (!strcasecmp(result, "restart")) { | |
1269 | unsigned int pos = 0; | |
b47382df BW |
1270 | fhp->speed = 0; |
1271 | switch_core_file_seek(fhp, &pos, 0, SEEK_SET); | |
8b8a7f14 BW |
1272 | return SWITCH_STATUS_SUCCESS; |
1273 | } else if (!strncasecmp(result, "seek", 4)) { | |
1274 | switch_codec_t *codec; | |
1275 | unsigned int samps = 0; | |
1276 | unsigned int pos = 0; | |
1277 | char *p; | |
1278 | codec = switch_core_session_get_read_codec(session); | |
4780a3d3 | 1279 | |
8b8a7f14 BW |
1280 | if ((p = strchr(result, ':'))) { |
1281 | p++; | |
1282 | if (*p == '+' || *p == '-') { | |
1283 | int step; | |
8052757a | 1284 | int32_t target; |
8b8a7f14 BW |
1285 | if (!(step = atoi(p))) { |
1286 | step = 1000; | |
1287 | } | |
4780a3d3 AM |
1288 | |
1289 | samps = step * (codec->implementation->samples_per_second / 1000); | |
8052757a | 1290 | target = (int32_t)fhp->pos + samps; |
4780a3d3 AM |
1291 | |
1292 | if (target < 0) { | |
1293 | target = 0; | |
8b8a7f14 | 1294 | } |
4780a3d3 | 1295 | |
8052757a | 1296 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target); |
4780a3d3 AM |
1297 | switch_core_file_seek(fhp, &pos, target, SEEK_SET); |
1298 | ||
e028f269 | 1299 | } else { |
8b8a7f14 | 1300 | samps = atoi(p) * (codec->implementation->samples_per_second / 1000); |
4780a3d3 AM |
1301 | if (samps < 0) { |
1302 | samps = 0; | |
1303 | } | |
1304 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps); | |
b47382df | 1305 | switch_core_file_seek(fhp, &pos, samps, SEEK_SET); |
e028f269 | 1306 | } |
e028f269 | 1307 | } |
e028f269 | 1308 | |
8b8a7f14 BW |
1309 | return SWITCH_STATUS_SUCCESS; |
1310 | } | |
1311 | } | |
b47382df | 1312 | |
fe854bdb | 1313 | if (!strcmp(result, "true") || !strcmp(result, "undefined")) { |
e028f269 MJ |
1314 | return SWITCH_STATUS_SUCCESS; |
1315 | } | |
1316 | ||
e028f269 | 1317 | |
c815c059 | 1318 | return SWITCH_STATUS_FALSE; |
e028f269 MJ |
1319 | } |
1320 | ||
83f84876 AM |
1321 | /* For Emacs: |
1322 | * Local Variables: | |
1323 | * mode:c | |
1324 | * indent-tabs-mode:t | |
1325 | * tab-width:4 | |
1326 | * c-basic-offset:4 | |
1327 | * End: | |
1328 | * For VIM: | |
64997c4d | 1329 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4: |
83f84876 | 1330 | */ |