2005-11-19 20:07:43 +00:00
|
|
|
/*
|
|
|
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
|
|
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
*
|
|
|
|
* Version: MPL 1.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Anthony Minessale II <anthmct@yahoo.com>
|
2006-09-18 05:08:55 +00:00
|
|
|
* Michael Jerris <mike@jerris.com>
|
2005-11-19 20:07:43 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* switch_channel.c -- Media Channel Interface
|
|
|
|
*
|
|
|
|
*/
|
2006-04-29 01:00:52 +00:00
|
|
|
#include <switch.h>
|
2006-04-29 06:05:03 +00:00
|
|
|
#include <switch_channel.h>
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-04-22 18:12:17 +00:00
|
|
|
struct switch_cause_table {
|
|
|
|
const char *name;
|
|
|
|
switch_call_cause_t cause;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct switch_cause_table CAUSE_CHART[] = {
|
|
|
|
{ "UNALLOCATED", SWITCH_CAUSE_UNALLOCATED },
|
2007-01-30 03:17:10 +00:00
|
|
|
{ "SUCCESS", SWITCH_CAUSE_SUCCESS },
|
2006-04-22 18:12:17 +00:00
|
|
|
{ "NO_ROUTE_TRANSIT_NET", SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET },
|
|
|
|
{ "NO_ROUTE_DESTINATION", SWITCH_CAUSE_NO_ROUTE_DESTINATION },
|
|
|
|
{ "CHANNEL_UNACCEPTABLE", SWITCH_CAUSE_CHANNEL_UNACCEPTABLE },
|
|
|
|
{ "CALL_AWARDED_DELIVERED", SWITCH_CAUSE_CALL_AWARDED_DELIVERED },
|
|
|
|
{ "NORMAL_CLEARING", SWITCH_CAUSE_NORMAL_CLEARING },
|
|
|
|
{ "USER_BUSY", SWITCH_CAUSE_USER_BUSY },
|
|
|
|
{ "NO_USER_RESPONSE", SWITCH_CAUSE_NO_USER_RESPONSE },
|
|
|
|
{ "NO_ANSWER", SWITCH_CAUSE_NO_ANSWER },
|
2006-10-25 03:45:20 +00:00
|
|
|
{ "SUBSCRIBER_ABSENT", SWITCH_CAUSE_SUBSCRIBER_ABSENT },
|
2006-04-22 18:12:17 +00:00
|
|
|
{ "CALL_REJECTED", SWITCH_CAUSE_CALL_REJECTED },
|
|
|
|
{ "NUMBER_CHANGED", SWITCH_CAUSE_NUMBER_CHANGED },
|
2006-10-25 03:45:20 +00:00
|
|
|
{ "REDIRECTION_TO_NEW_DESTINATION", SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION },
|
|
|
|
{ "EXCHANGE_ROUTING_ERROR", SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR },
|
2006-04-22 18:12:17 +00:00
|
|
|
{ "DESTINATION_OUT_OF_ORDER", SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER },
|
|
|
|
{ "INVALID_NUMBER_FORMAT", SWITCH_CAUSE_INVALID_NUMBER_FORMAT },
|
|
|
|
{ "FACILITY_REJECTED", SWITCH_CAUSE_FACILITY_REJECTED },
|
|
|
|
{ "RESPONSE_TO_STATUS_ENQUIRY", SWITCH_CAUSE_RESPONSE_TO_STATUS_ENQUIRY },
|
|
|
|
{ "NORMAL_UNSPECIFIED", SWITCH_CAUSE_NORMAL_UNSPECIFIED },
|
|
|
|
{ "NORMAL_CIRCUIT_CONGESTION", SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION },
|
|
|
|
{ "NETWORK_OUT_OF_ORDER", SWITCH_CAUSE_NETWORK_OUT_OF_ORDER },
|
|
|
|
{ "NORMAL_TEMPORARY_FAILURE", SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE },
|
|
|
|
{ "SWITCH_CONGESTION", SWITCH_CAUSE_SWITCH_CONGESTION },
|
|
|
|
{ "ACCESS_INFO_DISCARDED", SWITCH_CAUSE_ACCESS_INFO_DISCARDED },
|
|
|
|
{ "REQUESTED_CHAN_UNAVAIL", SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL },
|
|
|
|
{ "PRE_EMPTED", SWITCH_CAUSE_PRE_EMPTED },
|
|
|
|
{ "FACILITY_NOT_SUBSCRIBED", SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED },
|
|
|
|
{ "OUTGOING_CALL_BARRED", SWITCH_CAUSE_OUTGOING_CALL_BARRED },
|
|
|
|
{ "INCOMING_CALL_BARRED", SWITCH_CAUSE_INCOMING_CALL_BARRED },
|
|
|
|
{ "BEARERCAPABILITY_NOTAUTH", SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH },
|
|
|
|
{ "BEARERCAPABILITY_NOTAVAIL", SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL },
|
2006-10-25 03:45:20 +00:00
|
|
|
{ "SERVICE_UNAVAILABLE", SWITCH_CAUSE_SERVICE_UNAVAILABLE },
|
2006-04-22 18:12:17 +00:00
|
|
|
{ "CHAN_NOT_IMPLEMENTED", SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED },
|
|
|
|
{ "FACILITY_NOT_IMPLEMENTED", SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED },
|
2006-10-25 03:45:20 +00:00
|
|
|
{ "SERVICE_NOT_IMPLEMENTED", SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED },
|
2006-04-22 18:12:17 +00:00
|
|
|
{ "INVALID_CALL_REFERENCE", SWITCH_CAUSE_INVALID_CALL_REFERENCE },
|
|
|
|
{ "INCOMPATIBLE_DESTINATION", SWITCH_CAUSE_INCOMPATIBLE_DESTINATION },
|
|
|
|
{ "INVALID_MSG_UNSPECIFIED", SWITCH_CAUSE_INVALID_MSG_UNSPECIFIED },
|
|
|
|
{ "MANDATORY_IE_MISSING", SWITCH_CAUSE_MANDATORY_IE_MISSING },
|
|
|
|
{ "MESSAGE_TYPE_NONEXIST", SWITCH_CAUSE_MESSAGE_TYPE_NONEXIST },
|
|
|
|
{ "WRONG_MESSAGE", SWITCH_CAUSE_WRONG_MESSAGE },
|
|
|
|
{ "IE_NONEXIST", SWITCH_CAUSE_IE_NONEXIST },
|
|
|
|
{ "INVALID_IE_CONTENTS", SWITCH_CAUSE_INVALID_IE_CONTENTS },
|
|
|
|
{ "WRONG_CALL_STATE", SWITCH_CAUSE_WRONG_CALL_STATE },
|
|
|
|
{ "RECOVERY_ON_TIMER_EXPIRE", SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE },
|
|
|
|
{ "MANDATORY_IE_LENGTH_ERROR", SWITCH_CAUSE_MANDATORY_IE_LENGTH_ERROR },
|
|
|
|
{ "PROTOCOL_ERROR", SWITCH_CAUSE_PROTOCOL_ERROR },
|
|
|
|
{ "INTERWORKING", SWITCH_CAUSE_INTERWORKING },
|
2006-10-25 04:28:49 +00:00
|
|
|
{ "ORIGINATOR_CANCEL", SWITCH_CAUSE_ORIGINATOR_CANCEL },
|
2006-04-27 15:02:35 +00:00
|
|
|
{ "CRASH", SWITCH_CAUSE_CRASH },
|
2006-07-07 18:59:14 +00:00
|
|
|
{ "SYSTEM_SHUTDOWN", SWITCH_CAUSE_SYSTEM_SHUTDOWN },
|
2006-08-17 00:53:09 +00:00
|
|
|
{ "LOSE_RACE", SWITCH_CAUSE_LOSE_RACE },
|
2006-09-20 20:25:26 +00:00
|
|
|
{ "MANAGER_REQUEST", SWITCH_CAUSE_MANAGER_REQUEST },
|
2006-10-04 23:11:11 +00:00
|
|
|
{ "BLIND_TRANSFER", SWITCH_CAUSE_BLIND_TRANSFER },
|
|
|
|
{ "ATTENDED_TRANSFER", SWITCH_CAUSE_ATTENDED_TRANSFER },
|
2006-04-22 18:12:17 +00:00
|
|
|
{ NULL, 0 }
|
|
|
|
};
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
struct switch_channel {
|
|
|
|
char *name;
|
2006-04-29 06:05:03 +00:00
|
|
|
switch_buffer_t *dtmf_buffer;
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_t *dtmf_mutex;
|
2006-06-22 23:56:09 +00:00
|
|
|
switch_mutex_t *flag_mutex;
|
2006-04-28 19:46:57 +00:00
|
|
|
switch_mutex_t *profile_mutex;
|
2006-04-29 06:05:03 +00:00
|
|
|
switch_core_session_t *session;
|
2006-04-29 23:43:28 +00:00
|
|
|
switch_channel_state_t state;
|
2006-03-30 23:02:50 +00:00
|
|
|
uint32_t flags;
|
2006-09-19 02:18:24 +00:00
|
|
|
uint32_t state_flags;
|
2006-04-29 06:05:03 +00:00
|
|
|
switch_caller_profile_t *caller_profile;
|
|
|
|
const switch_state_handler_table_t *state_handlers[SWITCH_MAX_STATE_HANDLERS];
|
2006-02-07 20:47:15 +00:00
|
|
|
int state_handler_index;
|
2006-04-29 01:00:52 +00:00
|
|
|
switch_hash_t *variables;
|
2006-09-07 03:58:01 +00:00
|
|
|
switch_hash_t *private_hash;
|
2006-04-21 23:16:26 +00:00
|
|
|
switch_call_cause_t hangup_cause;
|
2005-11-19 20:07:43 +00:00
|
|
|
};
|
|
|
|
|
2006-04-22 18:12:17 +00:00
|
|
|
|
2006-04-26 20:15:16 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_channel_cause2str(switch_call_cause_t cause)
|
2006-04-22 18:12:17 +00:00
|
|
|
{
|
|
|
|
uint8_t x;
|
2007-01-26 20:39:45 +00:00
|
|
|
char *str = "UNKNOWN";
|
2006-04-22 18:12:17 +00:00
|
|
|
|
|
|
|
for(x = 0; CAUSE_CHART[x].name; x++) {
|
|
|
|
if (CAUSE_CHART[x].cause == cause) {
|
|
|
|
str = (char *) CAUSE_CHART[x].name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2006-04-26 20:15:16 +00:00
|
|
|
SWITCH_DECLARE(switch_call_cause_t) switch_channel_str2cause(char *str)
|
2006-04-22 18:12:17 +00:00
|
|
|
{
|
|
|
|
uint8_t x;
|
|
|
|
switch_call_cause_t cause = SWITCH_CAUSE_UNALLOCATED;
|
|
|
|
|
|
|
|
for(x = 0; CAUSE_CHART[x].name; x++) {
|
|
|
|
if (!strcasecmp(CAUSE_CHART[x].name, str)) {
|
|
|
|
cause = CAUSE_CHART[x].cause;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return cause;
|
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_call_cause_t) switch_channel_get_cause(switch_channel_t *channel)
|
2006-04-22 18:12:17 +00:00
|
|
|
{
|
2006-06-13 22:25:58 +00:00
|
|
|
assert(channel != NULL);
|
2006-04-22 18:12:17 +00:00
|
|
|
return channel->hangup_cause;
|
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_channel_timetable_t *) switch_channel_get_timetable(switch_channel_t *channel)
|
2006-02-24 22:22:43 +00:00
|
|
|
{
|
2006-12-01 15:26:37 +00:00
|
|
|
switch_channel_timetable_t *times = NULL;
|
|
|
|
|
2006-06-13 22:25:58 +00:00
|
|
|
assert(channel != NULL);
|
2006-12-01 15:26:37 +00:00
|
|
|
if (channel->caller_profile) {
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
times = channel->caller_profile->times;
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
return times;
|
2006-02-24 22:22:43 +00:00
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel, switch_memory_pool_t *pool)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(pool != NULL);
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
if (((*channel) = switch_core_alloc(pool, sizeof(switch_channel_t))) == 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_core_hash_init(&(*channel)->variables, pool);
|
2006-09-07 03:58:01 +00:00
|
|
|
switch_core_hash_init(&(*channel)->private_hash, pool);
|
2006-09-08 18:57:24 +00:00
|
|
|
switch_buffer_create_dynamic(&(*channel)->dtmf_buffer, 128, 128, 0);
|
|
|
|
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_init(&(*channel)->dtmf_mutex, SWITCH_MUTEX_NESTED, pool);
|
2006-06-22 23:56:09 +00:00
|
|
|
switch_mutex_init(&(*channel)->flag_mutex, SWITCH_MUTEX_NESTED, pool);
|
2006-04-28 19:46:57 +00:00
|
|
|
switch_mutex_init(&(*channel)->profile_mutex, SWITCH_MUTEX_NESTED, pool);
|
2006-04-22 18:12:17 +00:00
|
|
|
(*channel)->hangup_cause = SWITCH_CAUSE_UNALLOCATED;
|
2005-12-22 01:57:32 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_size_t) switch_channel_has_dtmf(switch_channel_t *channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-03-30 23:02:50 +00:00
|
|
|
switch_size_t has;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
assert(channel != NULL);
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_lock(channel->dtmf_mutex);
|
|
|
|
has = switch_buffer_inuse(channel->dtmf_buffer);
|
|
|
|
switch_mutex_unlock(channel->dtmf_mutex);
|
|
|
|
|
|
|
|
return has;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *channel, char *dtmf)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-04-29 23:43:28 +00:00
|
|
|
switch_status_t status;
|
2006-03-30 23:02:50 +00:00
|
|
|
register switch_size_t len, inuse;
|
2006-05-04 00:07:20 +00:00
|
|
|
switch_size_t wr = 0;
|
|
|
|
char *p;
|
2005-12-21 22:25:22 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
assert(channel != NULL);
|
|
|
|
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_lock(channel->dtmf_mutex);
|
2006-03-30 23:02:50 +00:00
|
|
|
|
|
|
|
inuse = switch_buffer_inuse(channel->dtmf_buffer);
|
|
|
|
len = strlen(dtmf);
|
|
|
|
|
|
|
|
if (len + inuse > switch_buffer_len(channel->dtmf_buffer)) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_buffer_toss(channel->dtmf_buffer, strlen(dtmf));
|
|
|
|
}
|
|
|
|
|
2006-05-04 00:07:20 +00:00
|
|
|
p = dtmf;
|
|
|
|
while(wr < len && p) {
|
2006-05-04 17:51:53 +00:00
|
|
|
if (is_dtmf(*p)) {
|
2006-05-04 00:07:20 +00:00
|
|
|
wr++;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2006-05-04 01:44:41 +00:00
|
|
|
p++;
|
2006-05-04 00:07:20 +00:00
|
|
|
}
|
|
|
|
status = switch_buffer_write(channel->dtmf_buffer, dtmf, wr) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_MEMERR;
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_unlock(channel->dtmf_mutex);
|
|
|
|
|
|
|
|
return status;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_size_t) switch_channel_dequeue_dtmf(switch_channel_t *channel, char *dtmf, switch_size_t len)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-03-31 16:10:00 +00:00
|
|
|
switch_size_t bytes;
|
2006-04-29 01:00:52 +00:00
|
|
|
switch_event_t *event;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
assert(channel != NULL);
|
2005-12-06 21:25:56 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(channel->dtmf_mutex);
|
2005-11-19 20:07:43 +00:00
|
|
|
if ((bytes = switch_buffer_read(channel->dtmf_buffer, dtmf, len)) > 0) {
|
|
|
|
*(dtmf + bytes) = '\0';
|
|
|
|
}
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_unlock(channel->dtmf_mutex);
|
|
|
|
|
2006-05-04 17:51:53 +00:00
|
|
|
if (bytes && switch_event_create(&event, SWITCH_EVENT_DTMF) == SWITCH_STATUS_SUCCESS) {
|
2005-12-21 22:25:22 +00:00
|
|
|
switch_channel_event_set_data(channel, event);
|
2007-02-13 04:43:49 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-String", "%s", dtmf);
|
2005-12-21 22:25:22 +00:00
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
2005-12-06 21:25:56 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
return bytes;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-09-08 18:57:24 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_uninit(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
switch_buffer_destroy(&channel->dtmf_buffer);
|
|
|
|
}
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_init(switch_channel_t *channel,
|
2006-04-29 06:05:03 +00:00
|
|
|
switch_core_session_t *session,
|
2006-04-29 23:43:28 +00:00
|
|
|
switch_channel_state_t state, uint32_t flags)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
|
|
|
channel->state = state;
|
|
|
|
channel->flags = flags;
|
|
|
|
channel->session = session;
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-10-21 04:58:15 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_presence(switch_channel_t *channel, char *rpid, char *status)
|
|
|
|
{
|
|
|
|
char *id = switch_channel_get_variable(channel, "presence_id");
|
|
|
|
switch_event_t *event;
|
|
|
|
switch_event_types_t type = SWITCH_EVENT_PRESENCE_IN;
|
|
|
|
|
|
|
|
if (!status) {
|
|
|
|
type = SWITCH_EVENT_PRESENCE_OUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!id) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_event_create(&event, type) == SWITCH_STATUS_SUCCESS) {
|
2007-02-13 04:43:49 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "%s", __FILE__);
|
2006-10-21 04:58:15 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", __FILE__);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", id);
|
|
|
|
if (type == SWITCH_EVENT_PRESENCE_IN) {
|
|
|
|
if (!rpid) {
|
|
|
|
rpid = "unknown";
|
|
|
|
}
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "%s", rpid);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "%s", status);
|
|
|
|
}
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_channel_get_variable(switch_channel_t *channel, char *varname)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
char *v = NULL;
|
2006-06-13 22:25:58 +00:00
|
|
|
assert(channel != NULL);
|
2006-10-20 06:55:30 +00:00
|
|
|
|
|
|
|
if (!(v=switch_core_hash_find(channel->variables, varname))) {
|
2006-12-01 15:26:37 +00:00
|
|
|
if (!channel->caller_profile || !(v = switch_caller_get_field_by_name(channel->caller_profile, varname))) {
|
2006-11-09 05:39:04 +00:00
|
|
|
if (!strcmp(varname, "base_dir")) {
|
|
|
|
return SWITCH_GLOBAL_dirs.base_dir;
|
|
|
|
}
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
v = switch_core_get_variable(varname);
|
2006-11-09 05:39:04 +00:00
|
|
|
}
|
2006-10-20 06:55:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return v;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-06-13 01:49:18 +00:00
|
|
|
SWITCH_DECLARE(switch_hash_index_t *) switch_channel_variable_first(switch_channel_t *channel, switch_memory_pool_t *pool)
|
|
|
|
{
|
2006-06-13 22:25:58 +00:00
|
|
|
assert(channel != NULL);
|
2006-06-13 01:49:18 +00:00
|
|
|
return switch_hash_first(pool, channel->variables);
|
|
|
|
}
|
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_private(switch_channel_t *channel, char *key, void *private_info)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
2006-09-07 03:58:01 +00:00
|
|
|
switch_core_hash_insert_dup(channel->private_hash, switch_core_session_strdup(channel->session, key), private_info);
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
SWITCH_DECLARE(void *) switch_channel_get_private(switch_channel_t *channel, char *key)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
2006-09-07 03:58:01 +00:00
|
|
|
return switch_core_hash_find(channel->private_hash, key);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_name(switch_channel_t *channel, char *name)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
|
|
|
channel->name = NULL;
|
|
|
|
if (name) {
|
2006-04-28 19:46:57 +00:00
|
|
|
char *uuid = switch_core_session_get_uuid(channel->session);
|
2005-11-19 20:07:43 +00:00
|
|
|
channel->name = switch_core_session_strdup(channel->session, name);
|
2006-04-28 19:46:57 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "New Chan %s [%s]\n", name, uuid);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_channel_get_name(switch_channel_t *channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
2006-05-03 17:03:27 +00:00
|
|
|
return channel->name ? channel->name : "N/A";
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2007-02-17 00:56:16 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable(switch_channel_t *channel, const char *varname, const char *value)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
2006-07-13 13:20:20 +00:00
|
|
|
if (varname) {
|
|
|
|
switch_core_hash_delete(channel->variables, varname);
|
2007-02-05 19:35:31 +00:00
|
|
|
if (!switch_strlen_zero(value)) {
|
2006-07-13 13:20:20 +00:00
|
|
|
switch_core_hash_insert_dup(channel->variables, varname, switch_core_session_strdup(channel->session, value));
|
|
|
|
} else {
|
|
|
|
switch_core_hash_delete(channel->variables, varname);
|
|
|
|
}
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-07-13 13:20:20 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2007-02-19 22:57:27 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_nodup(switch_channel_t *channel, const char *varname, char *value)
|
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
if (varname) {
|
|
|
|
switch_core_hash_delete(channel->variables, varname);
|
|
|
|
if (!switch_strlen_zero(value)) {
|
|
|
|
switch_core_hash_insert_dup(channel->variables, varname, value);
|
|
|
|
} else {
|
|
|
|
switch_core_hash_delete(channel->variables, varname);
|
|
|
|
}
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(int) switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flags)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-06-13 22:25:58 +00:00
|
|
|
assert(channel != NULL);
|
2006-03-30 23:02:50 +00:00
|
|
|
return switch_test_flag(channel, flags) ? 1 : 0;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_flag(switch_channel_t *channel, switch_channel_flag_t flags)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-06-13 22:25:58 +00:00
|
|
|
assert(channel != NULL);
|
2006-06-22 23:56:09 +00:00
|
|
|
switch_set_flag_locked(channel, flags);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-09-19 02:18:24 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_state_flag(switch_channel_t *channel, switch_channel_flag_t flags)
|
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
channel->state_flags |= flags;
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
}
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flags)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-06-13 22:25:58 +00:00
|
|
|
assert(channel != NULL);
|
2006-06-22 23:56:09 +00:00
|
|
|
switch_clear_flag_locked(channel, flags);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(switch_channel_state_t) switch_channel_get_state(switch_channel_t *channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-09-16 00:43:58 +00:00
|
|
|
switch_channel_state_t state;
|
2005-11-19 20:07:43 +00:00
|
|
|
assert(channel != NULL);
|
2006-09-16 00:43:58 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
state = channel->state;
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
|
|
|
|
return state;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-09-19 19:09:10 +00:00
|
|
|
SWITCH_DECLARE(uint8_t) switch_channel_ready(switch_channel_t *channel)
|
2006-03-01 22:55:28 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
2007-03-12 20:17:34 +00:00
|
|
|
|
|
|
|
return (!channel->hangup_cause && channel->state > CS_RING && channel->state < CS_HANGUP && !switch_test_flag(channel, CF_TRANSFER)) ? 1 : 0;
|
2006-03-01 22:55:28 +00:00
|
|
|
}
|
|
|
|
|
2005-12-21 22:25:22 +00:00
|
|
|
static const char *state_names[] = {
|
|
|
|
"CS_NEW",
|
|
|
|
"CS_INIT",
|
|
|
|
"CS_RING",
|
|
|
|
"CS_TRANSMIT",
|
|
|
|
"CS_EXECUTE",
|
|
|
|
"CS_LOOPBACK",
|
2006-04-28 19:46:57 +00:00
|
|
|
"CS_HOLD",
|
2006-10-31 21:38:06 +00:00
|
|
|
"CS_HIBERNATE",
|
2005-12-21 22:25:22 +00:00
|
|
|
"CS_HANGUP",
|
2006-06-06 23:07:37 +00:00
|
|
|
"CS_DONE",
|
|
|
|
NULL
|
2005-12-21 22:25:22 +00:00
|
|
|
};
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(const char *) switch_channel_state_name(switch_channel_state_t state)
|
2005-12-21 22:25:22 +00:00
|
|
|
{
|
|
|
|
return state_names[state];
|
|
|
|
}
|
|
|
|
|
2006-06-06 23:07:37 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_channel_state_t) switch_channel_name_state(char *name)
|
|
|
|
{
|
|
|
|
uint32_t x = 0;
|
|
|
|
for(x = 0; state_names[x]; x++) {
|
|
|
|
if (!strcasecmp(state_names[x], name)) {
|
|
|
|
return (switch_channel_state_t) x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return CS_DONE;
|
|
|
|
}
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_channel_t *channel,
|
2006-12-17 01:01:09 +00:00
|
|
|
const char *file,
|
2006-12-18 00:48:34 +00:00
|
|
|
const char *func,
|
2006-12-17 01:01:09 +00:00
|
|
|
int line,
|
|
|
|
switch_channel_state_t state)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-04-29 23:43:28 +00:00
|
|
|
switch_channel_state_t last_state;
|
2005-11-19 20:07:43 +00:00
|
|
|
int ok = 0;
|
2005-12-21 22:25:22 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
assert(channel != NULL);
|
2006-09-16 00:43:58 +00:00
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
last_state = channel->state;
|
|
|
|
|
|
|
|
if (last_state == state) {
|
2006-09-16 00:43:58 +00:00
|
|
|
goto done;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-02-13 17:37:10 +00:00
|
|
|
if (last_state >= CS_HANGUP && state < last_state) {
|
2006-09-16 00:43:58 +00:00
|
|
|
goto done;
|
2005-12-06 17:18:56 +00:00
|
|
|
}
|
2006-09-16 00:43:58 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
/* STUB for more dev
|
2006-01-20 15:05:05 +00:00
|
|
|
case CS_INIT:
|
|
|
|
switch(state) {
|
|
|
|
|
|
|
|
case CS_NEW:
|
|
|
|
case CS_INIT:
|
|
|
|
case CS_LOOPBACK:
|
|
|
|
case CS_TRANSMIT:
|
|
|
|
case CS_RING:
|
|
|
|
case CS_EXECUTE:
|
|
|
|
case CS_HANGUP:
|
|
|
|
case CS_DONE:
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
*/
|
|
|
|
|
|
|
|
switch (last_state) {
|
2006-01-20 02:02:03 +00:00
|
|
|
case CS_NEW:
|
2006-01-20 15:05:05 +00:00
|
|
|
switch (state) {
|
|
|
|
default:
|
|
|
|
ok++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-01-20 02:02:03 +00:00
|
|
|
case CS_INIT:
|
2006-01-20 15:05:05 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_LOOPBACK:
|
|
|
|
case CS_TRANSMIT:
|
|
|
|
case CS_RING:
|
|
|
|
case CS_EXECUTE:
|
2006-04-28 19:46:57 +00:00
|
|
|
case CS_HOLD:
|
2006-10-31 21:38:06 +00:00
|
|
|
case CS_HIBERNATE:
|
2006-01-20 15:05:05 +00:00
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
case CS_LOOPBACK:
|
2006-01-20 15:05:05 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_TRANSMIT:
|
|
|
|
case CS_RING:
|
|
|
|
case CS_EXECUTE:
|
2006-04-28 19:46:57 +00:00
|
|
|
case CS_HOLD:
|
2006-10-31 21:38:06 +00:00
|
|
|
case CS_HIBERNATE:
|
2006-01-20 15:05:05 +00:00
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
case CS_TRANSMIT:
|
2006-01-20 15:05:05 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_LOOPBACK:
|
|
|
|
case CS_RING:
|
|
|
|
case CS_EXECUTE:
|
2006-04-28 19:46:57 +00:00
|
|
|
case CS_HOLD:
|
2006-10-31 21:38:06 +00:00
|
|
|
case CS_HIBERNATE:
|
2006-04-28 19:46:57 +00:00
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CS_HOLD:
|
|
|
|
switch (state) {
|
|
|
|
case CS_LOOPBACK:
|
|
|
|
case CS_RING:
|
|
|
|
case CS_EXECUTE:
|
|
|
|
case CS_TRANSMIT:
|
2006-10-31 21:38:06 +00:00
|
|
|
case CS_HIBERNATE:
|
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CS_HIBERNATE:
|
|
|
|
switch (state) {
|
|
|
|
case CS_LOOPBACK:
|
|
|
|
case CS_RING:
|
|
|
|
case CS_EXECUTE:
|
|
|
|
case CS_TRANSMIT:
|
|
|
|
case CS_HOLD:
|
2006-01-20 15:05:05 +00:00
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
case CS_RING:
|
2006-04-28 19:46:57 +00:00
|
|
|
switch_clear_flag(channel, CF_TRANSFER);
|
2006-01-20 15:05:05 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_LOOPBACK:
|
|
|
|
case CS_EXECUTE:
|
|
|
|
case CS_TRANSMIT:
|
2006-04-28 19:46:57 +00:00
|
|
|
case CS_HOLD:
|
2006-10-31 21:38:06 +00:00
|
|
|
case CS_HIBERNATE:
|
2006-01-20 15:05:05 +00:00
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
case CS_EXECUTE:
|
2006-01-20 15:05:05 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_LOOPBACK:
|
|
|
|
case CS_TRANSMIT:
|
|
|
|
case CS_RING:
|
2006-04-28 19:46:57 +00:00
|
|
|
case CS_HOLD:
|
2006-10-31 21:38:06 +00:00
|
|
|
case CS_HIBERNATE:
|
2006-01-20 15:05:05 +00:00
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
case CS_HANGUP:
|
2006-01-20 15:05:05 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_DONE:
|
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
default:
|
2006-01-20 15:05:05 +00:00
|
|
|
break;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ok) {
|
2006-10-21 04:58:15 +00:00
|
|
|
if (state > CS_RING) {
|
|
|
|
switch_channel_presence(channel, "unknown", (char*)state_names[state]);
|
|
|
|
}
|
2007-02-13 21:03:06 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_DEBUG, "%s State Change %s -> %s\n",
|
2006-04-27 15:02:35 +00:00
|
|
|
channel->name,
|
|
|
|
state_names[last_state],
|
|
|
|
state_names[state]);
|
2006-09-12 17:17:02 +00:00
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
2005-11-19 20:07:43 +00:00
|
|
|
channel->state = state;
|
2006-09-12 17:17:02 +00:00
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
2006-04-22 18:12:17 +00:00
|
|
|
|
2007-01-26 20:39:45 +00:00
|
|
|
if (state == CS_HANGUP && !channel->hangup_cause) {
|
2006-04-22 18:12:17 +00:00
|
|
|
channel->hangup_cause = SWITCH_CAUSE_NORMAL_CLEARING;
|
|
|
|
}
|
2006-04-26 20:15:16 +00:00
|
|
|
if (state < CS_HANGUP) {
|
2006-04-29 01:00:52 +00:00
|
|
|
switch_event_t *event;
|
2006-04-26 20:15:16 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_STATE) == SWITCH_STATUS_SUCCESS) {
|
2006-07-22 21:49:52 +00:00
|
|
|
if (state == CS_RING) {
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
} else {
|
|
|
|
char state_num[25];
|
|
|
|
snprintf(state_num, sizeof(state_num), "%d", channel->state);
|
2007-02-13 04:43:49 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-State", "%s", (char *) switch_channel_state_name(channel->state));
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-State-Number", "%s", (char *) state_num);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Name", "%s", switch_channel_get_name(channel));
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Unique-ID", "%s", switch_core_session_get_uuid(channel->session));
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
2006-04-26 20:15:16 +00:00
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
2006-04-25 23:11:56 +00:00
|
|
|
}
|
2006-09-16 00:43:58 +00:00
|
|
|
|
2006-03-22 17:05:16 +00:00
|
|
|
if (state < CS_DONE) {
|
|
|
|
switch_core_session_signal_state_change(channel->session);
|
|
|
|
}
|
2006-09-16 00:43:58 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
} else {
|
2007-02-13 21:03:06 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_WARNING, "%s Invalid State Change %s -> %s\n",
|
2006-04-27 15:02:35 +00:00
|
|
|
channel->name,
|
|
|
|
state_names[last_state],
|
|
|
|
state_names[state]);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2007-03-04 01:46:08 +00:00
|
|
|
/* we won't tolerate an invalid state change so we can make sure we are as robust as a nice cup of dark coffee! */
|
2005-11-19 20:07:43 +00:00
|
|
|
if (channel->state < CS_HANGUP) {
|
2007-03-04 01:46:08 +00:00
|
|
|
/* not cool lets crash this bad boy and figure out wtf is going on */
|
2005-11-19 20:07:43 +00:00
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
}
|
2006-09-16 00:43:58 +00:00
|
|
|
done:
|
2006-09-19 02:18:24 +00:00
|
|
|
|
|
|
|
if (channel->state_flags) {
|
|
|
|
channel->flags |= channel->state_flags;
|
|
|
|
channel->state_flags = 0;
|
|
|
|
}
|
|
|
|
|
2006-09-16 00:43:58 +00:00
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
2005-11-19 20:07:43 +00:00
|
|
|
return channel->state;
|
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_event_set_data(switch_channel_t *channel, switch_event_t *event)
|
2005-12-21 22:25:22 +00:00
|
|
|
{
|
2006-12-01 15:26:37 +00:00
|
|
|
switch_caller_profile_t *caller_profile, *originator_caller_profile = NULL, *originatee_caller_profile = NULL;
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_hash_index_t *hi;
|
2006-07-20 03:55:07 +00:00
|
|
|
switch_codec_t *codec;
|
2005-12-21 22:25:22 +00:00
|
|
|
void *val;
|
|
|
|
const void *var;
|
2006-04-04 21:26:21 +00:00
|
|
|
char state_num[25];
|
2005-12-21 22:25:22 +00:00
|
|
|
|
2006-12-01 15:26:37 +00:00
|
|
|
if ((caller_profile = switch_channel_get_caller_profile(channel))) {
|
|
|
|
originator_caller_profile = caller_profile->originator_caller_profile;
|
|
|
|
originatee_caller_profile = caller_profile->originatee_caller_profile;
|
|
|
|
}
|
2006-01-03 01:17:59 +00:00
|
|
|
|
2007-02-23 17:28:41 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-State", "%s", switch_channel_state_name(channel->state));
|
2006-04-04 21:26:21 +00:00
|
|
|
snprintf(state_num, sizeof(state_num), "%d", channel->state);
|
2007-02-23 17:28:41 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-State-Number", "%s", state_num);
|
2007-02-13 04:43:49 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Name", "%s", switch_channel_get_name(channel));
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Unique-ID", "%s", switch_core_session_get_uuid(channel->session));
|
2006-07-20 03:55:07 +00:00
|
|
|
|
|
|
|
if ((codec = switch_core_session_get_read_codec(channel->session))) {
|
2007-02-23 17:28:41 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Name", "%s", switch_str_nil(codec->implementation->iananame));
|
2006-07-20 03:55:07 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Rate", "%u", codec->implementation->samples_per_second);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((codec = switch_core_session_get_write_codec(channel->session))) {
|
2007-02-23 17:28:41 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Name", "%s", switch_str_nil(codec->implementation->iananame));
|
2006-07-20 03:55:07 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Rate", "%u", codec->implementation->samples_per_second);
|
|
|
|
}
|
2005-12-21 22:25:22 +00:00
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
/* Index Caller's Profile */
|
2005-12-21 22:25:22 +00:00
|
|
|
if (caller_profile) {
|
2005-12-26 19:09:59 +00:00
|
|
|
switch_caller_profile_event_set_data(caller_profile, "Caller", event);
|
2005-12-21 22:25:22 +00:00
|
|
|
}
|
2006-01-03 01:17:59 +00:00
|
|
|
|
2005-12-21 22:25:22 +00:00
|
|
|
/* Index Originator's Profile */
|
|
|
|
if (originator_caller_profile) {
|
2005-12-26 19:09:59 +00:00
|
|
|
switch_caller_profile_event_set_data(originator_caller_profile, "Originator", event);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Index Originatee's Profile */
|
|
|
|
if (originatee_caller_profile) {
|
|
|
|
switch_caller_profile_event_set_data(originatee_caller_profile, "Originatee", event);
|
2005-12-21 22:25:22 +00:00
|
|
|
}
|
2005-12-23 21:09:36 +00:00
|
|
|
|
2005-12-21 22:25:22 +00:00
|
|
|
/* Index Variables */
|
2006-01-20 15:05:05 +00:00
|
|
|
for (hi = switch_hash_first(switch_core_session_get_pool(channel->session), channel->variables); hi;
|
|
|
|
hi = switch_hash_next(hi)) {
|
2005-12-21 22:25:22 +00:00
|
|
|
char buf[1024];
|
|
|
|
switch_hash_this(hi, &var, NULL, &val);
|
2007-02-23 17:28:41 +00:00
|
|
|
if (var && val) {
|
2007-02-23 20:02:41 +00:00
|
|
|
snprintf(buf, sizeof(buf), "variable_%s", (char *)var);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, buf, "%s", (char *)val);
|
2007-02-23 17:28:41 +00:00
|
|
|
}
|
2005-12-21 22:25:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
2006-02-22 02:50:33 +00:00
|
|
|
assert(channel->session != NULL);
|
2006-04-28 19:46:57 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2006-12-01 15:26:37 +00:00
|
|
|
assert(caller_profile != NULL);
|
2006-02-22 02:50:33 +00:00
|
|
|
|
|
|
|
if (!caller_profile->uuid) {
|
|
|
|
caller_profile->uuid = switch_core_session_strdup(channel->session, switch_core_session_get_uuid(channel->session));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!caller_profile->chan_name) {
|
|
|
|
caller_profile->chan_name = switch_core_session_strdup(channel->session, channel->name);
|
|
|
|
}
|
|
|
|
|
2006-05-10 03:23:05 +00:00
|
|
|
if (!caller_profile->context) {
|
|
|
|
caller_profile->chan_name = switch_core_session_strdup(channel->session, "default");
|
|
|
|
}
|
|
|
|
|
2006-04-04 21:26:21 +00:00
|
|
|
if (!channel->caller_profile) {
|
2006-04-29 01:00:52 +00:00
|
|
|
switch_event_t *event;
|
2006-04-04 21:26:21 +00:00
|
|
|
|
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CREATE) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
2006-04-28 19:46:57 +00:00
|
|
|
}
|
2006-12-01 15:26:37 +00:00
|
|
|
|
|
|
|
caller_profile->times = (switch_channel_timetable_t *) switch_core_session_alloc(channel->session, sizeof(*caller_profile->times));
|
|
|
|
caller_profile->times->created = switch_time_now();
|
|
|
|
|
|
|
|
if (channel->caller_profile && channel->caller_profile->times) {
|
|
|
|
channel->caller_profile->times->transferred = switch_time_now();
|
|
|
|
caller_profile->times->answered = channel->caller_profile->times->answered;
|
|
|
|
}
|
2006-04-04 21:26:21 +00:00
|
|
|
|
2006-04-28 19:46:57 +00:00
|
|
|
caller_profile->next = channel->caller_profile;
|
2005-11-19 20:07:43 +00:00
|
|
|
channel->caller_profile = caller_profile;
|
2006-04-28 19:46:57 +00:00
|
|
|
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_caller_profile(switch_channel_t *channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-04-29 06:05:03 +00:00
|
|
|
switch_caller_profile_t *profile;
|
2005-11-19 20:07:43 +00:00
|
|
|
assert(channel != NULL);
|
2006-04-28 19:46:57 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
profile = channel->caller_profile;
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
|
|
|
|
return profile;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_originator_caller_profile(switch_channel_t *channel,
|
|
|
|
switch_caller_profile_t *caller_profile)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
2006-12-01 15:26:37 +00:00
|
|
|
if (channel->caller_profile) {
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
caller_profile->next = channel->caller_profile->originator_caller_profile;
|
|
|
|
channel->caller_profile->originator_caller_profile = caller_profile;
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_originatee_caller_profile(switch_channel_t *channel,
|
|
|
|
switch_caller_profile_t *caller_profile)
|
2005-12-26 19:09:59 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
2006-12-01 15:26:37 +00:00
|
|
|
if (channel->caller_profile) {
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
caller_profile->next = channel->caller_profile->originatee_caller_profile;
|
|
|
|
channel->caller_profile->originatee_caller_profile = caller_profile;
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
2005-12-26 19:09:59 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originator_caller_profile(switch_channel_t *channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-12-01 15:26:37 +00:00
|
|
|
switch_caller_profile_t *profile = NULL;
|
2005-11-19 20:07:43 +00:00
|
|
|
assert(channel != NULL);
|
2006-04-28 19:46:57 +00:00
|
|
|
|
2006-12-01 15:26:37 +00:00
|
|
|
if (channel->caller_profile) {
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
profile = channel->caller_profile->originator_caller_profile;
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
2006-04-28 19:46:57 +00:00
|
|
|
|
|
|
|
return profile;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originatee_caller_profile(switch_channel_t *channel)
|
2005-12-26 19:09:59 +00:00
|
|
|
{
|
2006-12-01 15:26:37 +00:00
|
|
|
switch_caller_profile_t *profile = NULL;
|
2005-12-26 19:09:59 +00:00
|
|
|
assert(channel != NULL);
|
2006-04-28 19:46:57 +00:00
|
|
|
|
2006-12-01 15:26:37 +00:00
|
|
|
if (channel->caller_profile) {
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
profile = channel->caller_profile->originatee_caller_profile;
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
2006-04-28 19:46:57 +00:00
|
|
|
|
|
|
|
return profile;
|
2005-12-26 19:09:59 +00:00
|
|
|
}
|
|
|
|
|
2006-12-01 15:26:37 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_channel_get_uuid(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
|
|
|
assert(channel->session != NULL);
|
|
|
|
return switch_core_session_get_uuid(channel->session);
|
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(int) switch_channel_add_state_handler(switch_channel_t *channel,
|
|
|
|
const switch_state_handler_table_t *state_handler)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-08-15 21:38:24 +00:00
|
|
|
int x, index;
|
2006-02-07 22:58:56 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
assert(channel != NULL);
|
2006-10-04 23:11:11 +00:00
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
2006-08-15 21:38:24 +00:00
|
|
|
for (x = 0; x < SWITCH_MAX_STATE_HANDLERS; x++) {
|
|
|
|
if (channel->state_handlers[x] == state_handler) {
|
2006-10-04 23:11:11 +00:00
|
|
|
index = x;
|
|
|
|
goto end;
|
2006-08-15 21:38:24 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-07 22:58:56 +00:00
|
|
|
index = channel->state_handler_index++;
|
2006-02-07 20:47:15 +00:00
|
|
|
|
|
|
|
if (channel->state_handler_index >= SWITCH_MAX_STATE_HANDLERS) {
|
2006-10-04 23:11:11 +00:00
|
|
|
index = -1;
|
|
|
|
goto end;
|
2006-02-07 20:47:15 +00:00
|
|
|
}
|
2006-10-04 23:11:11 +00:00
|
|
|
|
2006-02-07 20:47:15 +00:00
|
|
|
channel->state_handlers[index] = state_handler;
|
2006-10-04 23:11:11 +00:00
|
|
|
|
|
|
|
end:
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
2006-02-07 20:47:15 +00:00
|
|
|
return index;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(const switch_state_handler_table_t *) switch_channel_get_state_handler(switch_channel_t *channel, int index)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-10-04 23:11:11 +00:00
|
|
|
const switch_state_handler_table_t *h = NULL;
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
assert(channel != NULL);
|
2006-02-07 20:47:15 +00:00
|
|
|
|
|
|
|
if (index > SWITCH_MAX_STATE_HANDLERS || index > channel->state_handler_index) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-10-04 23:11:11 +00:00
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
h = channel->state_handlers[index];
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
|
|
|
|
return h;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_clear_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
|
2006-04-25 18:02:12 +00:00
|
|
|
{
|
2006-10-04 23:11:11 +00:00
|
|
|
int index, i = channel->state_handler_index;
|
2006-04-29 06:05:03 +00:00
|
|
|
const switch_state_handler_table_t *new_handlers[SWITCH_MAX_STATE_HANDLERS] = {0};
|
2006-04-25 18:02:12 +00:00
|
|
|
|
2006-10-04 23:11:11 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
|
2006-04-25 18:02:12 +00:00
|
|
|
assert(channel != NULL);
|
2006-10-04 23:11:11 +00:00
|
|
|
channel->state_handler_index = 0;
|
2006-04-25 18:02:12 +00:00
|
|
|
|
2006-08-17 00:53:09 +00:00
|
|
|
if (state_handler) {
|
2006-10-04 23:11:11 +00:00
|
|
|
for (index = 0; index < i; index++) {
|
2006-08-17 00:53:09 +00:00
|
|
|
if (channel->state_handlers[index] != state_handler) {
|
2006-10-04 23:11:11 +00:00
|
|
|
new_handlers[channel->state_handler_index++] = channel->state_handlers[index];
|
2006-08-17 00:53:09 +00:00
|
|
|
}
|
2006-04-25 18:02:12 +00:00
|
|
|
}
|
|
|
|
}
|
2006-04-26 18:37:03 +00:00
|
|
|
for (index = 0; index < SWITCH_MAX_STATE_HANDLERS; index++) {
|
|
|
|
channel->state_handlers[index] = NULL;
|
|
|
|
}
|
2006-09-19 15:33:02 +00:00
|
|
|
|
2006-08-17 00:53:09 +00:00
|
|
|
if (state_handler) {
|
2006-10-04 23:11:11 +00:00
|
|
|
for (index = 0; index < channel->state_handler_index; index++) {
|
|
|
|
channel->state_handlers[index] = new_handlers[index];
|
2006-08-17 00:53:09 +00:00
|
|
|
}
|
2006-04-25 18:02:12 +00:00
|
|
|
}
|
|
|
|
|
2006-10-04 23:11:11 +00:00
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
|
2006-04-25 18:02:12 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel,
|
|
|
|
switch_caller_extension_t *caller_extension)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
2006-06-03 17:06:06 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2007-02-07 17:19:06 +00:00
|
|
|
caller_extension->next = channel->caller_profile->caller_extension;
|
|
|
|
channel->caller_profile->caller_extension = caller_extension;
|
2006-06-03 17:06:06 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_caller_extension(switch_channel_t *channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-02-07 17:19:06 +00:00
|
|
|
switch_caller_extension_t *extension;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
assert(channel != NULL);
|
2007-02-07 17:19:06 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
extension = channel->caller_profile->caller_extension;
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
return extension;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_channel_t *channel,
|
2006-12-17 01:01:09 +00:00
|
|
|
const char *file,
|
2006-12-18 00:48:34 +00:00
|
|
|
const char *func,
|
2006-12-17 01:01:09 +00:00
|
|
|
int line,
|
|
|
|
switch_call_cause_t hangup_cause)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
2006-09-16 00:43:58 +00:00
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
2006-04-03 14:53:34 +00:00
|
|
|
|
2006-12-01 15:26:37 +00:00
|
|
|
if (channel->caller_profile && channel->caller_profile->times && !channel->caller_profile->times->hungup) {
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
channel->caller_profile->times->hungup = switch_time_now();
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2006-04-03 14:53:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (channel->state < CS_HANGUP) {
|
2006-04-29 01:00:52 +00:00
|
|
|
switch_event_t *event;
|
2006-04-29 23:43:28 +00:00
|
|
|
switch_channel_state_t last_state = channel->state;
|
2005-11-19 20:07:43 +00:00
|
|
|
channel->state = CS_HANGUP;
|
2006-04-22 03:05:25 +00:00
|
|
|
channel->hangup_cause = hangup_cause;
|
2007-02-13 21:03:06 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_NOTICE, "Hangup %s [%s] [%s]\n",
|
2006-04-27 15:02:35 +00:00
|
|
|
channel->name,
|
2006-04-26 20:15:16 +00:00
|
|
|
state_names[last_state], switch_channel_cause2str(channel->hangup_cause));
|
2006-09-07 22:39:40 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP) == SWITCH_STATUS_SUCCESS) {
|
2007-02-13 04:43:49 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", "%s", switch_channel_cause2str(channel->hangup_cause));
|
2006-04-25 23:11:56 +00:00
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
2006-11-09 05:39:04 +00:00
|
|
|
|
|
|
|
switch_channel_set_variable(channel, "hangup_cause", switch_channel_cause2str(channel->hangup_cause));
|
2006-10-21 04:58:15 +00:00
|
|
|
switch_channel_presence(channel, "unavailable", switch_channel_cause2str(channel->hangup_cause));
|
|
|
|
|
2006-03-22 17:05:16 +00:00
|
|
|
switch_core_session_kill_channel(channel->session, SWITCH_SIG_KILL);
|
2006-09-16 00:43:58 +00:00
|
|
|
switch_core_session_signal_state_change(channel->session);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
2006-09-16 00:43:58 +00:00
|
|
|
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
2005-11-19 20:07:43 +00:00
|
|
|
return channel->state;
|
|
|
|
}
|
|
|
|
|
2007-02-13 02:32:10 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready(switch_channel_t *channel,
|
|
|
|
const char *file,
|
|
|
|
const char *func,
|
|
|
|
int line)
|
|
|
|
{
|
|
|
|
if (!switch_channel_test_flag(channel, CF_RING_READY)) {
|
2007-02-13 21:03:06 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_NOTICE, "Ring-Ready %s!\n", channel->name);
|
2007-02-13 02:32:10 +00:00
|
|
|
switch_channel_set_flag(channel, CF_RING_READY);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-02-09 01:34:01 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_channel_t *channel,
|
2007-02-13 02:32:10 +00:00
|
|
|
const char *file,
|
|
|
|
const char *func,
|
|
|
|
int line)
|
2007-02-09 01:34:01 +00:00
|
|
|
{
|
|
|
|
switch_event_t *event;
|
|
|
|
|
2007-02-13 02:32:10 +00:00
|
|
|
switch_channel_mark_ring_ready(channel);
|
|
|
|
|
2007-02-09 01:34:01 +00:00
|
|
|
if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
|
|
|
|
char *uuid;
|
|
|
|
switch_core_session_t *other_session;
|
|
|
|
|
2007-02-13 21:03:06 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_NOTICE, "Pre-Answer %s!\n", channel->name);
|
2007-02-09 01:34:01 +00:00
|
|
|
switch_channel_set_flag(channel, CF_EARLY_MEDIA);
|
|
|
|
switch_channel_set_variable(channel, "endpoint_disposition", "EARLY MEDIA");
|
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_PROGRESS) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
2007-03-21 21:23:40 +00:00
|
|
|
/* if we're the child of another channel and the other channel is in a blocking read they will never realize we have answered so send
|
2007-02-09 01:34:01 +00:00
|
|
|
a SWITCH_SIG_BREAK to interrupt any blocking reads on that channel
|
|
|
|
*/
|
2007-03-21 21:23:40 +00:00
|
|
|
if ((uuid = switch_channel_get_variable(channel, SWITCH_ORIGINATOR_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
|
2007-02-09 01:34:01 +00:00
|
|
|
switch_core_session_kill_channel(other_session, SWITCH_SIG_BREAK);
|
|
|
|
switch_core_session_rwunlock(other_session);
|
|
|
|
}
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_perform_pre_answer(switch_channel_t *channel,
|
2006-12-17 01:01:09 +00:00
|
|
|
const char *file,
|
2006-12-18 00:48:34 +00:00
|
|
|
const char *func,
|
2006-12-17 01:01:09 +00:00
|
|
|
int line)
|
2006-03-03 16:57:21 +00:00
|
|
|
{
|
2006-04-29 06:05:03 +00:00
|
|
|
switch_core_session_message_t msg;
|
2006-03-03 16:57:21 +00:00
|
|
|
char *uuid = switch_core_session_get_uuid(channel->session);
|
2006-04-29 23:43:28 +00:00
|
|
|
switch_status_t status;
|
2006-08-29 15:17:06 +00:00
|
|
|
|
2006-03-21 00:20:24 +00:00
|
|
|
assert(channel != NULL);
|
|
|
|
|
2007-03-12 20:17:34 +00:00
|
|
|
if (channel->hangup_cause || channel->state >= CS_HANGUP) {
|
2006-03-21 00:20:24 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2006-07-10 19:51:19 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_ANSWERED)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-10-08 15:51:10 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-03-03 16:57:21 +00:00
|
|
|
msg.message_id = SWITCH_MESSAGE_INDICATE_PROGRESS;
|
|
|
|
msg.from = channel->name;
|
|
|
|
status = switch_core_session_message_send(uuid, &msg);
|
2007-03-21 21:23:40 +00:00
|
|
|
|
2006-03-03 17:49:22 +00:00
|
|
|
if (status == SWITCH_STATUS_SUCCESS) {
|
2007-02-09 01:34:01 +00:00
|
|
|
status = switch_channel_perform_mark_pre_answered(channel, file, func, line);
|
2006-03-03 17:49:22 +00:00
|
|
|
}
|
2006-03-03 16:57:21 +00:00
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2007-02-13 14:58:06 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_perform_ring_ready(switch_channel_t *channel,
|
|
|
|
const char *file,
|
|
|
|
const char *func,
|
|
|
|
int line)
|
2006-10-25 04:28:49 +00:00
|
|
|
{
|
|
|
|
switch_core_session_message_t msg;
|
|
|
|
char *uuid = switch_core_session_get_uuid(channel->session);
|
|
|
|
switch_status_t status;
|
|
|
|
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
2007-03-12 20:17:34 +00:00
|
|
|
if (channel->hangup_cause || channel->state >= CS_HANGUP) {
|
2006-10-25 04:28:49 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_channel_test_flag(channel, CF_ANSWERED)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
msg.message_id = SWITCH_MESSAGE_INDICATE_RINGING;
|
|
|
|
msg.from = channel->name;
|
|
|
|
status = switch_core_session_message_send(uuid, &msg);
|
|
|
|
|
|
|
|
if (status == SWITCH_STATUS_SUCCESS) {
|
2007-02-13 21:03:06 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_NOTICE, "Ring Ready %s!\n", channel->name);
|
2006-10-25 04:28:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2006-12-05 23:08:14 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_channel_t *channel,
|
2006-12-17 01:01:09 +00:00
|
|
|
const char *file,
|
2006-12-18 00:48:34 +00:00
|
|
|
const char *func,
|
2006-12-17 01:01:09 +00:00
|
|
|
int line)
|
2006-12-05 23:08:14 +00:00
|
|
|
{
|
|
|
|
switch_event_t *event;
|
2007-02-09 01:34:01 +00:00
|
|
|
char *uuid;
|
|
|
|
switch_core_session_t *other_session;
|
2006-12-05 23:08:14 +00:00
|
|
|
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
2007-03-12 20:17:34 +00:00
|
|
|
if (channel->hangup_cause || channel->state >= CS_HANGUP) {
|
2006-12-05 23:08:14 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_channel_test_flag(channel, CF_ANSWERED)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (channel->caller_profile && channel->caller_profile->times) {
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
channel->caller_profile->times->answered = switch_time_now();
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_channel_set_flag(channel, CF_ANSWERED);
|
|
|
|
|
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_ANSWER) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
2007-03-21 21:23:40 +00:00
|
|
|
|
|
|
|
/* if we're the child of another channel and the other channel is in a blocking read they will never realize we have answered so send
|
2007-02-09 01:34:01 +00:00
|
|
|
a SWITCH_SIG_BREAK to interrupt any blocking reads on that channel
|
|
|
|
*/
|
2007-03-21 21:23:40 +00:00
|
|
|
if ((uuid = switch_channel_get_variable(channel, SWITCH_ORIGINATOR_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
|
2007-02-09 01:34:01 +00:00
|
|
|
switch_core_session_kill_channel(other_session, SWITCH_SIG_BREAK);
|
|
|
|
switch_core_session_rwunlock(other_session);
|
|
|
|
}
|
|
|
|
|
2007-01-26 15:42:38 +00:00
|
|
|
switch_channel_set_variable(channel, "endpoint_disposition", "ANSWER");
|
2007-02-13 21:03:06 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_NOTICE, "Channel [%s] has been answered\n", channel->name);
|
2006-12-05 23:08:14 +00:00
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_perform_answer(switch_channel_t *channel,
|
2006-12-17 01:01:09 +00:00
|
|
|
const char *file,
|
2006-12-18 00:48:34 +00:00
|
|
|
const char *func,
|
2006-12-17 01:01:09 +00:00
|
|
|
int line)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
2007-03-12 20:17:34 +00:00
|
|
|
if (channel->hangup_cause || channel->state >= CS_HANGUP) {
|
2006-03-21 00:20:24 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-06-06 23:49:02 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_ANSWERED)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
if (switch_core_session_answer_channel(channel->session) == SWITCH_STATUS_SUCCESS) {
|
2006-12-05 23:08:14 +00:00
|
|
|
return switch_channel_perform_mark_answered(channel, file, func, line);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
|
|
|
|
}
|
2006-10-07 19:54:04 +00:00
|
|
|
|
2006-12-07 00:36:00 +00:00
|
|
|
#define resize(l) {\
|
|
|
|
char *dp;\
|
|
|
|
olen += (len + l + block);\
|
|
|
|
cpos = c - data;\
|
|
|
|
if ((dp = realloc(data, olen))) {\
|
|
|
|
data = dp;\
|
|
|
|
c = data + cpos;\
|
|
|
|
memset(c, 0, olen - cpos);\
|
|
|
|
}} \
|
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel, char *in)
|
|
|
|
{
|
|
|
|
char *p, *c;
|
|
|
|
char *data, *indup;
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
size_t sp = 0, len = 0, olen = 0, vtype = 0, br = 0, cpos, block = 128;
|
2006-10-07 19:54:04 +00:00
|
|
|
char *sub_val = NULL, *func_val = NULL;
|
|
|
|
|
2007-02-25 22:44:36 +00:00
|
|
|
if (!in || !strchr(in, '$')) {
|
2006-10-07 19:54:04 +00:00
|
|
|
return in;
|
|
|
|
}
|
|
|
|
|
|
|
|
olen = strlen(in);
|
|
|
|
indup = strdup(in);
|
|
|
|
|
|
|
|
if ((data = malloc(olen))) {
|
|
|
|
memset(data, 0, olen);
|
|
|
|
c = data;
|
|
|
|
for(p = indup; *p; p++) {
|
|
|
|
vtype = 0;
|
|
|
|
|
|
|
|
if (*p == '$') {
|
|
|
|
vtype = 1;
|
2006-12-07 00:36:00 +00:00
|
|
|
if (*(p+1) != '{') {
|
|
|
|
vtype = 2;
|
|
|
|
}
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
2006-12-07 00:36:00 +00:00
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
if (vtype) {
|
|
|
|
char *s = p, *e, *vname, *vval = NULL;
|
2006-10-08 04:37:03 +00:00
|
|
|
size_t nlen;
|
2006-12-07 00:36:00 +00:00
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
s++;
|
2006-12-07 00:36:00 +00:00
|
|
|
|
2006-11-20 02:01:21 +00:00
|
|
|
if (vtype == 1 && *s == '{') {
|
2006-10-07 19:54:04 +00:00
|
|
|
br = 1;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
e = s;
|
|
|
|
vname = s;
|
|
|
|
while (*e) {
|
|
|
|
if (!br && *e == ' ') {
|
|
|
|
*e++ = '\0';
|
|
|
|
sp++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (br == 1 && *e == '}') {
|
|
|
|
br = 0;
|
|
|
|
*e++ = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (vtype == 2) {
|
|
|
|
if (*e == '(') {
|
|
|
|
*e++ = '\0';
|
|
|
|
vval = e;
|
|
|
|
br = 2;
|
|
|
|
}
|
|
|
|
if (br == 2 && *e == ')') {
|
|
|
|
*e++ = '\0';
|
|
|
|
br = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
e++;
|
|
|
|
}
|
|
|
|
p = e;
|
|
|
|
|
|
|
|
if (vtype == 1) {
|
|
|
|
sub_val = switch_channel_get_variable(channel, vname);
|
|
|
|
} else {
|
|
|
|
switch_stream_handle_t stream = {0};
|
|
|
|
|
|
|
|
SWITCH_STANDARD_STREAM(stream);
|
|
|
|
|
|
|
|
if (stream.data) {
|
|
|
|
if (switch_api_execute(vname, vval, channel->session, &stream) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
func_val = stream.data;
|
|
|
|
sub_val = func_val;
|
|
|
|
} else {
|
|
|
|
free(stream.data);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
|
|
|
|
free(data);
|
|
|
|
free(indup);
|
|
|
|
return in;
|
|
|
|
}
|
|
|
|
}
|
2006-11-26 20:06:04 +00:00
|
|
|
if ((nlen = sub_val ? strlen(sub_val) : 0)) {
|
|
|
|
if (len + nlen >= olen) {
|
2006-12-07 00:36:00 +00:00
|
|
|
resize(nlen);
|
2006-11-26 20:06:04 +00:00
|
|
|
}
|
|
|
|
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
len += nlen;
|
|
|
|
strcat(c, sub_val);
|
|
|
|
c += nlen;
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
|
|
|
|
switch_safe_free(func_val);
|
2006-12-07 00:36:00 +00:00
|
|
|
sub_val = NULL;
|
|
|
|
vname = NULL;
|
|
|
|
vtype = 0;
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
2006-12-07 00:36:00 +00:00
|
|
|
if (len + 1 >= olen) {
|
|
|
|
resize(1);
|
|
|
|
}
|
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
if (sp) {
|
|
|
|
*c++ = ' ';
|
|
|
|
sp = 0;
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
len++;
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
|
2006-12-06 17:19:07 +00:00
|
|
|
if (*p == '$') {
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
p--;
|
|
|
|
} else {
|
|
|
|
*c++ = *p;
|
|
|
|
len++;
|
|
|
|
}
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
free(indup);
|
|
|
|
return data;
|
|
|
|
}
|
2006-11-27 22:30:48 +00:00
|
|
|
|
|
|
|
/* For Emacs:
|
|
|
|
* Local Variables:
|
|
|
|
* mode:c
|
2007-02-09 02:36:03 +00:00
|
|
|
* indent-tabs-mode:t
|
2006-11-27 22:30:48 +00:00
|
|
|
* tab-width:4
|
|
|
|
* c-basic-offset:4
|
|
|
|
* End:
|
|
|
|
* For VIM:
|
|
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
|
|
*/
|